home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gdevstc.c < prev    next >
C/C++ Source or Header  |  1997-03-13  |  118KB  |  3,553 lines

  1. /* Copyright (C) 1995, 1996 Aladdin Enterprises.  All rights reserved.
  2.   This file is part of Aladdin Ghostscript.
  3.  
  4.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  5.   or distributor accepts any responsibility for the consequences of using it,
  6.   or for whether it serves any particular purpose or works at all, unless he
  7.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  8.   License (the "License") for full details.
  9.  
  10.   Every copy of Aladdin Ghostscript must include a copy of the License,
  11.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  12.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  13.   under certain conditions described in the License.  Among other things, the
  14.   License requires that the copyright notice and this notice be preserved on
  15.   all copies.
  16. */
  17.  
  18. /* gdevstc.c */
  19. /* Epson Stylus-Color Printer-Driver */
  20.  
  21. /***
  22.  *** This file was "copied" from gdevcdj.c (ghostscript-3.12), which was
  23.  *** contributed by:
  24.  ***    George Cameron      - g.cameron@biomed.abdn.ac.ukis
  25.  ***    Koert Zeilstra      - koert@zen.cais.com
  26.  ***    Eckhard Rueggeberg  - eckhard@ts.go.dlr.de
  27.  ***
  28.  *** Some of the ESC/P2-code was drawn from gdevescp.c, contributed by
  29.  ***    Richard Brown       - rab@eos.ncsu.edu
  30.  ***
  31.  *** The POSIX-Interrupt-Code is from (Compile-Time-Option -DSTC_SIGNAL)
  32.  ***    Frederic Loyer      - loyer@ensta.fr
  33.  ***
  34.  *** And several improvements are based on discussions with
  35.  ***    Brian Converse      - BCONVERSE@ids.net
  36.  ***    Bill Davidson       - bdavidson@ra.isisnet.com
  37.  ***    Gero Guenther       - gero@cs.tu-berlin.de
  38.  ***    Jason Patterson     - jason@reflections.com.au
  39.  ***    ? Rueschstroer      - rue@ibe.med.uni-muenchen.de
  40.  ***    Steven Singer       - S.Singer@ph.surrey.ac.uk
  41.  ***
  42.  *** And the remaining little rest, mainly the bugs, were written by me:
  43.  *** Gunther Hess           - gunther@elmos.de
  44.  ***
  45.  *** P.S.: there is some documentation, see devices.doc
  46.  ***
  47.  *** Revision-History:
  48.  *** 16-DEC-1994  1.1  - initial Version (GS-Dithering & Plain-Write)
  49.      ...
  50.  *** 30-JAN-1995  1.11 - FS-Improvements, u/sWeave, 1/4/24-Bits
  51.  ***  5-MAR-1995  1.12 - L. Peter Deutsch - updated put_params routine
  52.                          (first distributed version with gs3.33)
  53.  *** 26-APR-1995  1.13 - merged Peters fixes with algorithmic changes:
  54.                          Changed 24Bit-Mode, added 32Bit-Mode (moves colors)
  55.                          [Arrgh: much better than 1.12, but patch was lost]
  56.  ***  5-JUN-1995  1.14 - Added Color-Correction & Transfer-Curves
  57.                          (Several Beta-Testers, but not distributed)
  58.      ...
  59.  *** 24-JUL-1995  1.16 - Made dithering-Algorithms external-functions.
  60.                          (Mailed for Beta-Distribution)
  61.  *** 10-AUG-1995  1.17 - Several Bug-Fixes and some new features:
  62.                          CMYK10-Coding added
  63.                          Readonly Parameters added
  64.                           "Algorithms", "BitsPerComponent", "Version"
  65.                          Parameters Flag0-4, Model, OutputCode
  66.                          (mailed for distribution)
  67.  *** 14-SEP-1995  1.18   Fixes Bugs with Borland C (gs3.47)
  68.  *** 23-SEP-1995  1.19 - reorganized printcode + bug-fixing
  69.  *** 24-SEP-1995  1.20 - Little Cleanup for the release
  70.  *** 25-SEP-1995  1.21 - Readonly-Parameters added to put_params.
  71.  *** 31-Dec-1995  1.22 - Sanitary Engineering on the code
  72.  *** 16-Jan-1996  1.23 - Added String escp_Release
  73.  ***  8-May-1996  1.90 - Reintroduced Deltarow & Fixed MEMORY-BUG!
  74.  ***/
  75.  
  76. #include "gdevstc.h"
  77. #ifdef    STC_SIGNAL
  78. #  include <signal.h>
  79. #endif /* STC_SIGNAL */
  80. /***
  81.  *** Mode-Table - the various algorithms
  82.  *** (The intention is, that this source can live alone)
  83.  ***/
  84.  
  85. private stc_proc_dither(stc_gscmyk);   /* resides in this file */
  86. private stc_proc_dither(stc_hscmyk);   /* resides in this file */
  87.  
  88. #include <stdlib.h> /* for rand, used in stc_hscmyk */
  89.  
  90. private const stc_dither_t stc_dither[] = {
  91.   {"gscmyk", stc_gscmyk, DeviceCMYK|STC_BYTE|STC_DIRECT,0,{0.0,1.0}},
  92.   {"hscmyk", stc_hscmyk,
  93.   DeviceCMYK|STC_LONG|STC_CMYK10|STC_DIRECT|1*STC_SCAN,1+2*4,
  94.                                                   {0.0,    1023.0}},
  95.   STC_MODI
  96.   { NULL   , NULL      , 0,                  0,{0.0,0.0}}
  97. };
  98.  
  99. /***
  100.  ***  forward-declarations of routines
  101.  ***/
  102.  
  103. /* Primary Device functions
  104.  * (I've the idea to rename the driver to stc)
  105.  */
  106. private dev_proc_print_page(stc_print_page);
  107. private dev_proc_open_device(stc_open);
  108. private dev_proc_close_device(stc_close);
  109. private dev_proc_get_params(stc_get_params);
  110. private dev_proc_put_params(stc_put_params);
  111.  
  112. /*
  113.  * Color-Mapping-functions.
  114.  */
  115.  
  116. /* routines for monochrome monochrome modi */
  117. private dev_proc_map_rgb_color(stc_map_gray_color);
  118. private dev_proc_map_color_rgb(stc_map_color_gray);
  119.  
  120. /* routines for RGB-Modi */
  121. private dev_proc_map_rgb_color(stc_map_rgb_color);
  122. private dev_proc_map_color_rgb(stc_map_color_rgb);
  123.  
  124. /* routines for general CMYK-Modi */
  125. private dev_proc_map_cmyk_color(stc_map_cmyk_color);
  126. private dev_proc_map_color_rgb(stc_map_color_cmyk);
  127.  
  128. /* routines for 10Bit/Component CMYK */
  129. private dev_proc_map_cmyk_color(stc_map_cmyk10_color);
  130. private dev_proc_map_color_rgb(stc_map_color_cmyk10);
  131.  
  132. /***
  133.  *** Table of Device-Procedures
  134.  ***/
  135. private gx_device_procs stcolor_procs = {
  136.         stc_open,
  137.         gx_default_get_initial_matrix,
  138.         gx_default_sync_output,
  139.         gdev_prn_output_page,
  140.         stc_close,
  141.         NULL,
  142.         stc_map_color_cmyk,
  143.         NULL,   /* fill_rectangle */
  144.         NULL,   /* tile_rectangle */
  145.         NULL,   /* copy_mono */
  146.         NULL,   /* copy_color */
  147.         NULL,   /* draw_line */
  148.         gx_default_get_bits,
  149.         stc_get_params,
  150.         stc_put_params,
  151.         stc_map_cmyk_color
  152. };
  153.  
  154. /***
  155.  *** A local dummy-array for extvals
  156.  ***/
  157.  
  158. private float defext[] = { 0.0, 1.0 };
  159.  
  160. /***
  161.  *** Main device-control structure
  162.  ***/
  163. stcolor_device far_data gs_stcolor_device = {
  164.    prn_device_body(stcolor_device, stcolor_procs, "stcolor",
  165.       DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
  166.       X_DPI,  Y_DPI,
  167.       STC_L_MARGIN,STC_B_MARGIN,STC_R_MARGIN,STC_T_MARGIN,
  168.       4,  4, 1, 1, 2, 2,            /* default: cmyk-direct */
  169.       stc_print_page),
  170.      {STCNWEAVE,                    /* stcflags:  noWeave/bidirectional */
  171.       1,                            /* stcbits:   matches the default */
  172.       stc_dither,                   /* stcdither: first algorithm */
  173.       NULL,                         /* stcam:     NULL -> not used */
  174.       { NULL, NULL, NULL, NULL},    /* extcode:   none defined yet */
  175.       {    0,    0,    0,    0},    /* sizcode:   0, since no extcode yet */
  176.       { NULL, NULL, NULL, NULL},    /* stccode:   computed by put_params */
  177.       {defext,defext,defext,defext},/* extvals:   default */
  178.       {    2,    2,    2,    2},    /* sizvals:   default countof(defext) */
  179.       { NULL, NULL, NULL, NULL},    /* stcvals:   computed by put_params */
  180.       {    0,    0,    0},          /* white-run */
  181.       {    0,    0,    0},          /* white-end */
  182.       {NULL,0,false},               /* algorithm-table */
  183.       {NULL,0,false},               /* initialization-String (BOP) */
  184.       {NULL,0,false},               /* release-String (EOP) */
  185.       0,0,0,0,                      /* New escp-stuff */
  186.       1}                            /* itemsize used by algorithm */
  187. };
  188. /***
  189.  *** Test for white scan-lines
  190.  ***/
  191. private bool stc_iswhite(P3(stcolor_device *, int, byte *));
  192.  
  193. /***
  194.  *** Functions used for conversion inside the print-loop
  195.  ***/
  196. #define stc_proc_iconvert(Name) \
  197. byte * Name(P4(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line))
  198.  
  199. private stc_proc_iconvert(stc_any_depth);    /* general input-conversion */
  200. private stc_proc_iconvert(stc_rgb24_long);   /* 24Bit RGB  -> long's */
  201.  
  202. private stc_proc_iconvert(stc_cmyk32_long);  /* 32Bit CMYK -> long's */
  203. private stc_proc_iconvert(stc_any_direct);   /* use ext_data as input */
  204.  
  205. private stc_proc_iconvert(stc_cmyk10_byte);  /* CMYK10->vals-> any type */
  206. private stc_proc_iconvert(stc_cmyk10_long);  /* CMYK10->vals-> any type */
  207. private stc_proc_iconvert(stc_cmyk10_float); /* CMYK10->vals-> any type */
  208. private stc_proc_iconvert(stc_cmyk10_dbyte); /* CMYK10 direct bytes */
  209. private stc_proc_iconvert(stc_cmyk10_dlong); /* CMYK10 direct longs */
  210.  
  211. /***
  212.  *** Print-functions
  213.  ***/
  214. private void stc_print_weave(P2(stcolor_device *sd,FILE *prn_stream));
  215. private void stc_print_bands(P2(stcolor_device *sd,FILE *prn_stream));
  216. private void stc_print_delta(P2(stcolor_device *sd,FILE *prn_stream));
  217. private int  stc_print_setup(P1(stcolor_device *sd));
  218.  
  219. /***
  220.  *** compute the ESC/P2 specific values
  221.  ***/
  222.  
  223. private int 
  224. stc_print_setup(stcolor_device *sd) 
  225. {
  226.  
  227. /*
  228.  * Compute the resolution-parameters
  229.  */
  230.    sd->stc.escp_u = 3600.0 / sd->y_pixels_per_inch; /* y-units */
  231.    sd->stc.escp_h = 3600.0 / sd->x_pixels_per_inch; /* x-units */
  232.    sd->stc.escp_v = sd->stc.flags & (STCUWEAVE | STCNWEAVE) ?
  233.                     sd->stc.escp_u : 40;
  234. /*
  235.  * Initialize color
  236.  */
  237.    sd->stc.escp_c = 0; /* preselect-black */
  238.  
  239. /*
  240.  * Band-Width
  241.  */
  242.    if((sd->stc.flags & STCBAND) == 0) {
  243.       if(sd->stc.escp_v != sd->stc.escp_u)            sd->stc.escp_m = 15;
  244.       else if(STCSTCII == (sd->stc.flags & STCMODEL)) sd->stc.escp_m =  1;
  245.       else if(  sd->stc.flags & STCUWEAVE)            sd->stc.escp_m =  1;
  246.       else if((sd->stc.escp_v == sd->stc.escp_u) &&
  247.               (sd->stc.escp_u == 5))                  sd->stc.escp_m =  1;
  248.       else                                            sd->stc.escp_m =  1;
  249.    }
  250.  
  251. /*
  252.  * Page-Dimensions
  253.  */
  254.    if((sd->stc.flags & STCWIDTH ) == 0)
  255.        sd->stc.escp_width = sd->width -
  256.            (dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch;
  257.  
  258.    if((sd->stc.flags & STCHEIGHT) == 0)
  259.        sd->stc.escp_height = sd->height;
  260.  
  261.    if((sd->stc.flags & STCTOP) == 0)
  262.        sd->stc.escp_top = dev_t_margin(sd)*sd->y_pixels_per_inch;
  263.  
  264.    if((sd->stc.flags & STCBOTTOM) == 0)
  265.       sd->stc.escp_bottom = sd->height - dev_b_margin(sd)*sd->y_pixels_per_inch;
  266.  
  267.    if((sd->stc.flags & STCINIT) == 0) { /* No Initialization-String defined */
  268.       int need  = 8  /* Reset, Graphics-Mode 1 */
  269.                 + 6  /* MicroWeave */
  270.                 + 6  /* Select Units */
  271.                 + 7  /* Set Page-Length */
  272.                 + 9  /* Set Margins */
  273.                 + 3; /* Select Unidirectionality */
  274.       byte *bp  = (byte *) (sd->stc.escp_init.data);
  275.  
  276.       if(need != sd->stc.escp_init.size) {  /* Reallocate */
  277.  
  278.          if(NULL != (bp = gs_malloc(need,1,"stcolor/init"))) { /* Replace */
  279.             if(0 != sd->stc.escp_init.size)
  280.                gs_free((byte *)sd->stc.escp_init.data,sd->stc.escp_init.size,1,
  281.                        "stcolor/init");
  282.             sd->stc.escp_init.data       = bp;
  283.             sd->stc.escp_init.size       = need;
  284.             sd->stc.escp_init.persistent = false;
  285.          }  else {                                             /* Replace */
  286.              return_error(gs_error_VMerror);
  287.          }
  288.       }
  289.  
  290.       if(need != 39) return_error(gs_error_unregistered);
  291.  
  292.       memcpy(bp,
  293. /*                       1 1 11  1 11  1   1 1  2 22 2  2 22  2 22 3  3 3333  3 33*/
  294. /* 0 1  2 34  5  6 7  8 90 1 23  4 56  7   8 9  0 12 3  4 56  7 89 0  1 2345  6 78*/
  295. "\033@\033(G\001\0\1\033(i\1\0w\033(U\001\000u\033(C\2\000hh\033(c\4\000ttbb\033U",
  296.              need);
  297.  
  298.  
  299.       if((sd->stc.flags & STCUWEAVE) != 0) bp[13] = '\1';
  300.       else                                 bp[13] = '\0';
  301.  
  302.       bp[19] =  sd->stc.escp_u;
  303.  
  304.       bp[25] =  sd->stc.escp_height     & 0xff;
  305.       bp[26] = (sd->stc.escp_height>>8) & 0xff;
  306.  
  307.       bp[32] =  sd->stc.escp_top        & 0xff;
  308.       bp[33] = (sd->stc.escp_top>>8)    & 0xff;
  309.       bp[34] =  sd->stc.escp_bottom     & 0xff;
  310.       bp[35] = (sd->stc.escp_bottom>>8) & 0xff;
  311.  
  312.       if(sd->stc.flags & STCUNIDIR)        bp[38] = 1;
  313.       else                                 bp[38] = 0;
  314.  
  315.    }                                    /* No Initialization-String defined */
  316.  
  317.    if((sd->stc.flags & STCRELEASE) == 0) { /* No Release-String defined */
  318.       int need  = 3;  /* ESC @ \f */
  319.       byte *bp  = (byte *) (sd->stc.escp_release.data);
  320.  
  321.       if(need != sd->stc.escp_release.size) {  /* Reallocate */
  322.  
  323.          if(NULL != (bp = gs_malloc(need,1,"stcolor/release"))) { /* Replace */
  324.             if(0 != sd->stc.escp_release.size)
  325.                gs_free((byte *)sd->stc.escp_release.data,sd->stc.escp_release.size,1,
  326.                        "stcolor/release");
  327.             sd->stc.escp_release.data       = bp;
  328.             sd->stc.escp_release.size       = need;
  329.             sd->stc.escp_release.persistent = false;
  330.          }  else {                                             /* Replace */
  331.              return_error(gs_error_VMerror);
  332.          }
  333.       }
  334.  
  335.       if(need != 3) return_error(gs_error_unregistered);
  336.  
  337.       memcpy(bp,"\033@\f",need);
  338.  
  339.    }                                    /* No Release-String defined */
  340.  
  341.    return 0;
  342. }
  343.  
  344. /***
  345.  *** stc_print_page: here we go to do the nasty work
  346.  ***/
  347.  
  348. private int
  349. stc_print_page(gx_device_printer * pdev, FILE * prn_stream)
  350. {
  351.    stcolor_device *sd    = (stcolor_device *) pdev;
  352.    long            flags = sd == NULL ? 0 : sd->stc.flags;
  353.  
  354.    int  npass;           /* # of print-passes (softweave) */
  355.  
  356.    int    ext_size;      /* size of a ghostscript-scanline */
  357.    byte  *ext_line;      /* dyn: for this scanline */
  358.  
  359.    int    alg_size;      /* size of a scanline for the dithering-algorithm */
  360.    byte  *alg_line;      /* dyn: 1 scanline for the dithering-algorithm */
  361.    int    buf_size;      /* size of the private-buffer for dither-function */
  362.    byte  *buf;           /* dyn: the private buffer */
  363.  
  364.    int    prt_pixels;    /* Number of pixels printed */
  365.    byte  *col_line;      /* A Line with a byte per pixel */
  366.  
  367. #define OK4GO        ((flags &   STCOK4GO)              != 0)
  368. #define SORRY        ( flags &= ~STCOK4GO)
  369.  
  370.    if(0 > (npass = stc_print_setup(sd))) return_error(npass);
  371.  
  372.    npass = sd->stc.escp_v / sd->stc.escp_u;
  373.  
  374. /***
  375.  *** Allocate dynamic memory
  376.  ***/
  377.  
  378.    ext_size   = gdev_prn_raster(sd);
  379.    ext_line   = gs_malloc(ext_size,1,"stc_print_page/ext_line");
  380.    if(ext_line == NULL) SORRY;
  381.  
  382.    prt_pixels        = sd->stc.escp_width;
  383.    sd->stc.prt_size  = (prt_pixels+7)/8;
  384.    prt_pixels        =  sd->stc.prt_size * 8;
  385.  
  386.    sd->stc.prt_scans  = sd->height -
  387.       (dev_t_margin(sd)+dev_b_margin(sd))*sd->y_pixels_per_inch;
  388.  
  389.    col_line   = gs_malloc(prt_pixels,1,"stc_print_page/col_line");
  390.    if(col_line == NULL) SORRY;
  391.  
  392.    alg_size  = prt_pixels;
  393.    alg_size *= sd->color_info.num_components;
  394.  
  395.    if((sd->stc.dither->flags & STC_DIRECT) ||
  396.       ((sd->stc.bits                 == 8) &&
  397.        (sd->stc.alg_item                     == 1)))  {
  398.       alg_line = NULL;
  399.    } else {
  400.       alg_line = gs_malloc(alg_size,sd->stc.alg_item,"stc_print_page/alg_line");
  401.       if(alg_line == NULL) SORRY;
  402.    }
  403.  
  404.    buf_size = sd->stc.dither->bufadd
  405.             + alg_size*(sd->stc.dither->flags/STC_SCAN);
  406.    if(buf_size > 0) {
  407.       buf    = gs_malloc(buf_size,sd->stc.alg_item,"stc_print_page/buf");
  408.       if(buf == NULL) SORRY;
  409.    } else {
  410.       buf = NULL;
  411.    }
  412.  
  413. /*
  414.  * compute the number of printer-buffers
  415.  */
  416.  
  417.     for(sd->stc.prt_buf   = 16; sd->stc.prt_buf < (sd->stc.escp_m * npass);
  418.         sd->stc.prt_buf <<= 1);
  419.     if(sd->color_info.num_components > 1) sd->stc.prt_buf *= 4;
  420.  
  421.     sd->stc.prt_width = gs_malloc(sd->stc.prt_buf,sizeof(int),
  422.                         "stc_print_page/prt_width");
  423.     if(sd->stc.prt_width == NULL) SORRY;
  424.  
  425.     sd->stc.prt_data  = gs_malloc(sd->stc.prt_buf,sizeof(byte *),
  426.                         "stc_print_page/prt_data");
  427.  
  428.     if(sd->stc.prt_data == NULL) {
  429.        SORRY;
  430.     } else {
  431.        int i;
  432.  
  433.        for(i = 0; i < sd->stc.prt_buf; ++i) {
  434.           sd->stc.prt_data[i] = gs_malloc(sd->stc.prt_size,1,
  435.                                 "stc_print_page/prt");
  436.           if(sd->stc.prt_data[i] == NULL) SORRY;
  437.        }
  438.     }
  439.  
  440.     sd->stc.seed_size = (sd->stc.prt_size + 2*sizeof(int) - 1)/sizeof(int);
  441.     {
  442.        int i;
  443.        for(i = 0; i < sd->color_info.num_components; ++i) {
  444.           if((flags & STCCOMP) == STCDELTA) {
  445.              sd->stc.seed_row[i] = gs_malloc(sd->stc.seed_size,sizeof(int),
  446.                                    "stc_print_page/seed_row");
  447.              if(sd->stc.seed_row[i] == NULL) SORRY;
  448.              else memset(sd->stc.seed_row[i],0,sd->stc.seed_size*sizeof(int));
  449.           } else {
  450.              sd->stc.seed_row[i] = NULL;
  451.           }
  452.        }
  453.        while(i < countof(sd->stc.seed_row)) sd->stc.seed_row[i++] = NULL;
  454.     }
  455.  
  456.     switch(flags & STCCOMP) {
  457.        case STCPLAIN:
  458.           sd->stc.escp_size = 64 + sd->stc.prt_size;
  459.           break;
  460.        case STCDELTA:
  461.           sd->stc.escp_size = 64 + 2 * sd->stc.prt_size;
  462.           break;
  463.        default:
  464.           sd->stc.escp_size = 64 +
  465.                               sd->stc.prt_size + (sd->stc.prt_size + 127)/128;
  466.           break;
  467.     }
  468.  
  469.     sd->stc.escp_data = gs_malloc(sd->stc.escp_size,1,
  470.                                   "stc_print_page/escp_data");
  471.     if(sd->stc.escp_data == NULL) SORRY;
  472.  
  473. /*
  474.  * If we're still ok, we can print something
  475.  */
  476.  
  477.    if(OK4GO) {
  478.  
  479.       int ncolor;
  480.       int buf_i;
  481.       stc_proc_iconvert((*iconvert)) = stc_any_depth;
  482.  
  483. /*
  484.  * initialize col_line
  485.  */
  486.       if(sd->color_info.num_components == 3) {
  487.          memset(col_line,RED|GREEN|BLUE,prt_pixels);
  488.       } else {
  489.          memset(col_line,0,             prt_pixels);
  490.       }
  491.  
  492. /*
  493.  * select proper conversion for input to algorithm
  494.  */
  495.       if(     (sd->stc.dither->flags & STC_DIRECT ) ||
  496.               ((sd->stc.bits                 == 8) &&
  497.                (sd->stc.alg_item                     == 1)))
  498.          iconvert = stc_any_direct;
  499.       else if((sd->color_info.num_components ==  3) &&
  500.               (sd->color_info.depth          == 24) &&
  501.               (sizeof(long)                  == sd->stc.alg_item))
  502.          iconvert = stc_rgb24_long;
  503.       else if(sd->stc.flags & STCCMYK10) {
  504.          if(     ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
  505.                  ( sd->stc.dither->minmax[0]         ==    0.0  ))
  506.             iconvert = stc_cmyk10_dbyte;
  507.          else if ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)
  508.             iconvert = stc_cmyk10_byte;
  509.          else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
  510.                  ( sd->stc.dither->minmax[0]         ==    0.0  ) &&
  511.                  ( sd->stc.dither->minmax[1]         <= 1023.0  ))
  512.             iconvert = stc_cmyk10_dlong;
  513.          else if( (sd->stc.dither->flags & STC_TYPE) == STC_LONG)
  514.             iconvert = stc_cmyk10_long;
  515.          else
  516.             iconvert = stc_cmyk10_float;
  517.       }
  518.       else if((sd->color_info.num_components ==  4) &&
  519.               (sd->color_info.depth          == 32) &&
  520.               (sizeof(long)                  == sd->stc.alg_item))
  521.          iconvert = stc_cmyk32_long;
  522.  
  523. /*
  524.  * initialize the algorithm
  525.  */
  526.  
  527.       if((*sd->stc.dither->fun)(sd,-prt_pixels,alg_line,buf,col_line) < 0)
  528.          SORRY;
  529.  
  530. /*
  531.  * Main-Print-Loop
  532.  */
  533.  
  534.       if(OK4GO) {
  535. #ifdef    STC_SIGNAL
  536.          sigset_t stc_int_mask, stc_int_save, stc_int_pending;
  537.  
  538.          sigemptyset(&stc_int_mask);
  539.          sigaddset(&stc_int_mask,SIGINT);
  540.          sigprocmask(SIG_BLOCK,&stc_int_mask, &stc_int_save);
  541. #endif /* STC_SIGNAL */
  542.  
  543.  
  544.          if(sd->color_info.num_components > 1) ncolor = 4;
  545.          else                                  ncolor = 1;
  546.  
  547. /*
  548.  * Decide, wether we Adjust Linefeeds or not. (I hate it here)
  549.  */
  550.          if((0   == ((sd->stc.escp_m*sd->stc.escp_u) % 10)) &&
  551.             (256  > ((sd->stc.escp_m*sd->stc.escp_u) / 10))) sd->stc.escp_lf = sd->stc.escp_m;
  552.          else                                                sd->stc.escp_lf = 0;
  553.  
  554. /*
  555.  * prepare run-values, then loop over scans
  556.  */
  557.          sd->stc.stc_y      =  0; /* current printer y-Position */
  558.          sd->stc.buf_y      =  0; /* Top-Position within the buffer */
  559.          sd->stc.prt_y      =  0; /* physical position of the printer */
  560.          buf_i              =  0; /* next free line in buffer */
  561.          sd->stc.flags     &= ~STCPRINT; /* no data yet */
  562.  
  563.          while(sd->stc.stc_y < sd->stc.prt_scans) {  /* Until all scans are processed */
  564.             int need;
  565.  
  566.             need = sd->stc.stc_y + npass * sd->stc.escp_m;
  567.  
  568.             if(sd->stc.buf_y < need) { /* Nr. 5 (give me input) */
  569.  
  570. /* read as much as the buffer can hold */
  571.                if(ncolor == 1) need = sd->stc.stc_y +  sd->stc.prt_buf;
  572.                else            need = sd->stc.stc_y + (sd->stc.prt_buf>>2);
  573.  
  574.                for(;sd->stc.buf_y < need;
  575.                     buf_i = (sd->stc.prt_buf-1) & (buf_i+ncolor),
  576.                     ++sd->stc.buf_y) {
  577.  
  578.                   int color;
  579.                   byte *ext_data;
  580.                   byte *alg_data;
  581.  
  582. /* initialize output data 1st -> may take shortcut */
  583.  
  584.                   for(color = 0; color < ncolor; ++color) {
  585.                      memset(sd->stc.prt_data[buf_i+color],0,sd->stc.prt_size);
  586.                      sd->stc.prt_width[buf_i+color] = 0;
  587.                   }
  588.  
  589.  
  590. /* "read data", immediately continue if all is white */
  591.  
  592.                   if(sd->stc.buf_y < sd->stc.prt_scans) {  /* Test for White */
  593.  
  594.                      gdev_prn_get_bits(pdev,sd->stc.buf_y,ext_line,&ext_data);
  595.  
  596.                      color = stc_iswhite(sd,prt_pixels,ext_data) ? ext_size : 0;
  597.  
  598.                   } else {
  599.  
  600.                      color = ext_size;
  601.  
  602.                   }                        /* Test for White */
  603.  
  604.                   if(color >= ext_size) {  /* bypass processing */
  605.  
  606.                      if(sd->stc.dither->flags & STC_WHITE)
  607.                         (*sd->stc.dither->fun)(sd,prt_pixels,NULL,buf,col_line);
  608.                      continue;
  609.  
  610.                   }                        /* bypass processing */
  611.  
  612. /* convert data for the various cases */
  613.  
  614.                   alg_data = (*iconvert)(sd,ext_data,prt_pixels,alg_line);
  615.  
  616.  
  617. /*
  618.  * invoke the dithering-algorithm
  619.  */
  620.  
  621.                   (*sd->stc.dither->fun)(sd,prt_pixels,alg_data,buf,col_line);
  622. /*
  623.  * convert col_line to printer-format (separate colors)
  624.  */
  625.                   switch(sd->color_info.num_components) {
  626.                   case 1: /* Black & White: just merge into 8 Bytes */
  627.                   {
  628.                       byte *bytein,*byteout;
  629.                       int   width;
  630.  
  631.                       bytein  = col_line;
  632.                       byteout = sd->stc.prt_data[buf_i];
  633.  
  634.                       for(width = 1; width <= sd->stc.prt_size; ++width) {
  635.                           byte tmp = 0;
  636.                           byte i;
  637.  
  638.                           for(i = 128; i; i >>= 1) if(*bytein++) tmp  |= i;
  639.  
  640.                           if(tmp != 0) sd->stc.prt_width[buf_i] = width;
  641.  
  642.                           *byteout++ = tmp;
  643.                       }
  644.                   }
  645.                   break;
  646.                   case 3: /* convert rgb into cmyk */
  647.                   {
  648.                       byte *bytein;
  649.                       int   width;
  650.  
  651.                       bytein  = col_line;
  652.  
  653.                       for(width = 0; width < sd->stc.prt_size; ++width) {
  654.                          byte i,tmp,cmyk[4];
  655.  
  656.                          memset(cmyk,0,4);
  657.  
  658.                          for(i = 128; i; i >>= 1) {
  659.                             static const byte rgb2cmyk[] = {
  660.                                BLACK,            /* 0->Black */
  661.                                CYAN | MAGENTA,   /* 1->BLUE  */
  662.                                CYAN | YELLOW,    /* 2->GREEN */
  663.                                CYAN,             /* 3->CYAN  */
  664.                                MAGENTA | YELLOW, /* 4->RED   */
  665.                                MAGENTA,          /* 5->MAGENTA */
  666.                                YELLOW,           /* 6->YELLOW */
  667.                                0};               /* 7->WHITE */
  668.  
  669.                             tmp = rgb2cmyk[(*bytein++) & 7];
  670.  
  671.                             if(tmp & BLACK)   cmyk[3] |= i;
  672.                             if(tmp & YELLOW)  cmyk[2] |= i;
  673.                             if(tmp & MAGENTA) cmyk[1] |= i;
  674.                             if(tmp & CYAN)    cmyk[0] |= i;
  675.                          }
  676.  
  677.                          for(i = 0; i < 4; ++i) {
  678.                             if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
  679.                             sd->stc.prt_data[buf_i+i][width] = cmyk[i];
  680.                          }
  681.                       }
  682.                   }
  683.                   break;
  684.                   case 4: /* split cmyk */
  685.                   {
  686.                       byte *bytein;
  687.                       int   width;
  688.  
  689.                       bytein  = col_line;
  690.  
  691.                       for(width = 0; width < sd->stc.prt_size; ++width) {
  692.                          byte i,tmp,cmyk[4];
  693.  
  694.                          memset(cmyk,0,4);
  695.  
  696.                          for(i = 128; i; i >>= 1) {
  697.                             tmp = (*bytein++) & 15;
  698.                             if(tmp & BLACK)   cmyk[3] |= i;
  699.                             if(tmp & YELLOW)  cmyk[2] |= i;
  700.                             if(tmp & MAGENTA) cmyk[1] |= i;
  701.                             if(tmp & CYAN)    cmyk[0] |= i;
  702.                          }
  703.  
  704.                          for(i = 0; i < 4; ++i) {
  705.                             if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
  706.                             sd->stc.prt_data[buf_i+i][width] = cmyk[i];
  707.                          }
  708.                       }
  709.                   }
  710.                   break;
  711.                   default: break;
  712.                   }
  713.                }
  714.             }                  /* Nr. 5 (give me input) */
  715.  
  716. /*
  717.  *    Nr. 5 has got enough input, now we should print it
  718.  */
  719.             if((flags & STCCOMP) == STCDELTA) stc_print_delta(sd,prn_stream);
  720.             else if(npass > 1)                stc_print_weave(sd,prn_stream);
  721.             else                              stc_print_bands(sd,prn_stream);
  722.  
  723. #ifdef    STC_SIGNAL
  724.             sigpending(&stc_int_pending);
  725.             if(sigismember(&stc_int_pending,SIGINT)) {
  726.                fputs("\033@[Aborted]\f", prn_stream);
  727.                fflush(prn_stream);
  728.                sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
  729.                break;
  730.             }
  731. #endif /* STC_SIGNAL */
  732.  
  733.          }                           /* Until all scans are processed */
  734.  
  735.          if(sd->stc.flags & STCPRINT) {
  736.             if((flags & STCCOMP) == STCDELTA) fputc(0xe3,prn_stream);
  737.             fwrite(sd->stc.escp_release.data,1,sd->stc.escp_release.size,prn_stream);
  738.             fflush(prn_stream);
  739.          }
  740. #ifdef    STC_SIGNAL
  741.          sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
  742. #endif /* STC_DIGNAL */
  743.   
  744.       }
  745.    }
  746.  
  747. /***
  748.  *** Release the dynamic memory
  749.  ***/
  750.  
  751.    if(ext_line != NULL)
  752.       gs_free(ext_line,ext_size,1,"stc_print_page/ext_line");
  753.  
  754.    if(col_line != NULL)
  755.       gs_free(col_line,prt_pixels,1,"stc_print_page/col_line");
  756.  
  757.    if(alg_line != NULL)
  758.       gs_free(alg_line,alg_size,sd->stc.alg_item,
  759.          "stc_print_page/alg_line");
  760.  
  761.    if(buf != NULL)
  762.       gs_free(buf,buf_size,sd->stc.alg_item,"stc_print_page/buf");
  763.  
  764.     if(sd->stc.prt_width != NULL)
  765.        gs_free(sd->stc.prt_width,sd->stc.prt_buf,sizeof(int),
  766.        "stc_print_page/prt_width");
  767.  
  768.     if(sd->stc.prt_data != NULL) {
  769.        int i;
  770.  
  771.        for(i = 0; i < sd->stc.prt_buf; ++i) {
  772.           if(sd->stc.prt_data[i] != NULL)
  773.              gs_free(sd->stc.prt_data[i],sd->stc.prt_size,1,
  774.              "stc_print_page/prt");
  775.        }
  776.  
  777.        gs_free(sd->stc.prt_data,sd->stc.prt_buf,sizeof(byte *),
  778.        "stc_print_page/prt_data");
  779.     }
  780.  
  781.     {
  782.        int i;
  783.        for(i = 0; i < sd->color_info.num_components; ++i) {
  784.           if(sd->stc.seed_row[i] != NULL)
  785.             gs_free(sd->stc.seed_row[i],sd->stc.seed_size,sizeof(int),
  786.             "stc_print_page/seed_row");
  787.        }
  788.     }
  789.  
  790.     if(sd->stc.escp_data != NULL)
  791.        gs_free(sd->stc.escp_data,sd->stc.escp_size,1,
  792.        "stc_print_page/escp_data");
  793.  
  794.    return OK4GO ? 0 : gs_error_undefined;
  795. }
  796.  
  797. /*
  798.  * white-check
  799.  */
  800. private bool 
  801. stc_iswhite(stcolor_device *sd, int prt_pixels,byte *ext_data)
  802. {
  803.    long  b2do = (prt_pixels*sd->color_info.depth+7)>>3;
  804.    int   bcmp = 4 * countof(sd->stc.white_run);
  805.    byte *wht  = (byte *) sd->stc.white_run;
  806.  
  807.    while(b2do >= bcmp) {
  808.       if(memcmp(ext_data,wht,bcmp)) break;
  809.       ext_data += bcmp;
  810.       b2do     -= bcmp;
  811.    }
  812.  
  813.    if((b2do > 0) && (b2do < bcmp))
  814.       b2do  = memcmp(ext_data,sd->stc.white_end,b2do);
  815.  
  816.    return b2do ? false : true;
  817. }
  818.  
  819. /***
  820.  *** A bunch of routines that convert gslines into algorithms format.
  821.  ***/
  822. private byte *
  823. stc_any_depth(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
  824. { /* general conversion */
  825.  
  826.    int p,c,       niext,         nbits;
  827.    gx_color_index ciext,ci,cimsk,cvmsk;
  828.    byte          *ap = alg_line;
  829.  
  830.    nbits =  sd->stc.bits;
  831.    cvmsk = ((gx_color_index) 1<<nbits) - 1;
  832.  
  833. /* it is nonsense to use this algorithm for this cases, but if it claims
  834.  * generality, it should deliver correct results in this cases too */
  835.    if(sd->color_info.depth == (sd->color_info.num_components<<3)) nbits = 8;
  836.  
  837.    cimsk = cvmsk;
  838.    for(c = 1; c < sd->color_info.num_components; ++c)
  839.        cimsk = (cimsk<<nbits) | cvmsk;
  840.  
  841.    ciext = 0;
  842.    niext = 0;
  843.  
  844.    for(p = 0; p < prt_pixels; ++p) { /* over pixels */
  845.  
  846.       ci = ciext;
  847.       for(c =  sd->color_info.depth-niext; c >= 8; c -= 8)
  848.          ci  = (ci<<8) | *ext_data++;
  849.  
  850.       if(c > 0) {         /* partial byte required */
  851.  
  852.          niext  = 8 - c;
  853.          ciext  = *ext_data++;
  854.          ci     = (ci<<c) | (ciext>>niext);
  855.          ciext &= (1L<<niext)-1;
  856.  
  857.       } else if(c < 0) { /* some bits left in ciext */
  858.  
  859.          niext  = -c;
  860.          ciext &= (1L<<niext)-1;
  861.          ci     = ci>>niext;
  862.  
  863.       } else {           /* entire ciext used */
  864.  
  865.          niext = 0;
  866.          ciext = 0;
  867.  
  868.       }                  /* ciext-adjust */
  869.  
  870.       ci &= cimsk;
  871.  
  872. #     define stc_storeapc(T) \
  873.          ((T *)ap)[c] = ((T *)(sd->stc.vals[c]))[ci & cvmsk];
  874.  
  875.       for(c = sd->color_info.num_components; c--;) { /* comp */
  876.          STC_TYPESWITCH(sd->stc.dither,stc_storeapc)
  877.          ci >>= nbits;
  878.       }                                              /* comp */
  879.  
  880. #     undef  stc_storeapc
  881.  
  882.       ap += sd->color_info.num_components * sd->stc.alg_item;
  883.  
  884.    }                                 /* over pixels */
  885.  
  886.    return alg_line;
  887. } /* general conversion */
  888.  
  889. /*
  890.  * rgb-data with depth=24, can use a faster algorithm
  891.  */
  892. private byte *
  893. stc_rgb24_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
  894. { /* convert 3 bytes into appropriate long-Values */
  895.   register int   p;
  896.   register long *out   = (long *) alg_line;
  897.   register long *rvals = (long *) (sd->stc.vals[0]);
  898.   register long *gvals = (long *) (sd->stc.vals[1]);
  899.   register long *bvals = (long *) (sd->stc.vals[2]);
  900.  
  901.   for(p = prt_pixels; p; --p) {
  902.      *out++ = rvals[*ext_data++];
  903.      *out++ = gvals[*ext_data++];
  904.      *out++ = bvals[*ext_data++];
  905.   }
  906.  
  907.   return alg_line;
  908. } /* convert 3 bytes into appropriate long-Values */
  909.  
  910. /*
  911.  * cmyk-data with depth=32, can use a faster algorithm
  912.  */
  913. private byte *
  914. stc_cmyk32_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
  915. { /* convert 4 bytes into appropriate long-Values */
  916.   register int   p;
  917.   register long *out   = (long *) alg_line;
  918.   register long *cvals = (long *) (sd->stc.vals[0]);
  919.   register long *mvals = (long *) (sd->stc.vals[1]);
  920.   register long *yvals = (long *) (sd->stc.vals[2]);
  921.   register long *kvals = (long *) (sd->stc.vals[3]);
  922.  
  923.   for(p = prt_pixels; p; --p) {
  924.      *out++ = cvals[*ext_data++];
  925.      *out++ = mvals[*ext_data++];
  926.      *out++ = yvals[*ext_data++];
  927.      *out++ = kvals[*ext_data++];
  928.   }
  929.  
  930.   return alg_line;
  931. } /* convert 4 bytes into appropriate long-Values */
  932.  
  933. /*
  934.  * handle indirect encoded cmyk-data
  935.  */
  936. #define STC_CMYK10_ANY(T)\
  937.                                                                             \
  938.       register int p               = prt_pixels;                            \
  939.       register stc_pixel      ci,k,n,mode;                                  \
  940.       register stc_pixel      *in  = (stc_pixel *) ext_data;                \
  941.       register T              *out = (T *) alg_line;                        \
  942.       register T              *cv  = (T *) sd->stc.vals[0];                 \
  943.       register T              *mv  = (T *) sd->stc.vals[1];                 \
  944.       register T              *yv  = (T *) sd->stc.vals[2];                 \
  945.       register T              *kv  = (T *) sd->stc.vals[3];                 \
  946.                                                                             \
  947.       while(p--) {                                                          \
  948.          ci   = *in++;                                                      \
  949.          mode = ci & 3;                                                     \
  950.          k    = (ci>>2) & 0x3ff;                                            \
  951.          if(mode == 3) {                                                    \
  952.             *out++ = cv[0];                                                 \
  953.             *out++ = mv[0];                                                 \
  954.             *out++ = yv[0];                                                 \
  955.             *out++ = kv[k];                                                 \
  956.          } else {                                                           \
  957.             out[3] = kv[k];                                                 \
  958.             n = (ci>>12) & 0x3ff;                                           \
  959.             if(mode == 2) { out[2] = yv[k]; }                               \
  960.             else          { out[2] = yv[n]; n = (ci>>22) & 0x3ff; }         \
  961.             if(mode == 1) { out[1] = mv[k]; }                               \
  962.             else          { out[1] = mv[n]; n = (ci>>22) & 0x3ff; }         \
  963.             if(mode == 0)   out[0] = cv[k];                                 \
  964.             else            out[0] = cv[n];                                 \
  965.             out += 4;                                                       \
  966.          }                                                                  \
  967.       }                                                                     \
  968.                                                                             \
  969.       return alg_line;
  970.  
  971. private byte *
  972. stc_cmyk10_byte(stcolor_device *sd,
  973.                 byte *ext_data,int prt_pixels,byte *alg_line)
  974. {
  975.    STC_CMYK10_ANY(byte)
  976. }
  977. private byte *
  978. stc_cmyk10_long(stcolor_device *sd,
  979.                 byte *ext_data,int prt_pixels,byte *alg_line)
  980. {
  981.    STC_CMYK10_ANY(long)
  982. }
  983. private byte *
  984. stc_cmyk10_float(stcolor_device *sd,
  985.                 byte *ext_data,int prt_pixels,byte *alg_line)
  986. {
  987.    STC_CMYK10_ANY(float)
  988. }
  989.  
  990. #undef  STC_CMYK10_ANY
  991.  
  992. #define STC_CMYK10_DANY(T)\
  993.                                                                             \
  994.       register int p               = prt_pixels;                            \
  995.       register stc_pixel       ci,k,n,mode;                                 \
  996.       register stc_pixel      *in  = (stc_pixel *) ext_data;                \
  997.       register T              *out = (T *) alg_line;                        \
  998.                                                                             \
  999.       while(p--) {                                                          \
  1000.          ci   = *in++;                                                      \
  1001.          mode = ci & 3;                                                     \
  1002.          k    = (ci>>2) & 0x3ff;                                            \
  1003.          if(mode == 3) {                                                    \
  1004.             *out++ = 0;                                                     \
  1005.             *out++ = 0;                                                     \
  1006.             *out++ = 0;                                                     \
  1007.             *out++ = k;                                                     \
  1008.          } else {                                                           \
  1009.             out[3] = k;                                                     \
  1010.             n = (ci>>12) & 0x3ff;                                           \
  1011.             if(mode == 2) { out[2] = k; }                                   \
  1012.             else          { out[2] = n; n = (ci>>22) & 0x3ff; }             \
  1013.             if(mode == 1) { out[1] = k; }                                   \
  1014.             else          { out[1] = n; n = (ci>>22) & 0x3ff; }             \
  1015.             if(mode == 0)   out[0] = k;                                     \
  1016.             else            out[0] = n;                                     \
  1017.             out += 4;                                                       \
  1018.          }                                                                  \
  1019.       }                                                                     \
  1020.                                                                             \
  1021.       return alg_line;
  1022.  
  1023.  
  1024. private byte *
  1025. stc_cmyk10_dbyte(stcolor_device *sd,
  1026.                 byte *ext_data,int prt_pixels,byte *alg_line)
  1027. {
  1028.    STC_CMYK10_DANY(byte)
  1029. }
  1030. private byte *
  1031. stc_cmyk10_dlong(stcolor_device *sd,
  1032.                 byte *ext_data,int prt_pixels,byte *alg_line)
  1033. {
  1034.    STC_CMYK10_DANY(long)
  1035. }
  1036.  
  1037. #undef  STC_CMYK10_DANY
  1038.  
  1039. /*
  1040.  * if the algorithm uses bytes & bytes are in ext_data, use them
  1041.  */
  1042. /*ARGSUSED*/
  1043. private byte *
  1044. stc_any_direct(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
  1045. { /* return ext_data */
  1046.   return ext_data;
  1047. } /* return ext_data */
  1048.  
  1049. /* ----------------------------------------------------------------------- */
  1050. /* stc_rle: epson ESC/P2 RLE-Encoding
  1051.  */
  1052. private int 
  1053. stc_rle(byte *out,const byte *in,int width)
  1054. {
  1055.  
  1056.    int used = 0;
  1057.    int crun,cdata;
  1058.    byte run;
  1059.  
  1060.    if(in != NULL) { /* Data present */
  1061.  
  1062.       crun = 1;
  1063.  
  1064.       while(width > 0) { /* something to compress */
  1065.  
  1066.          run = in[0];
  1067.  
  1068.          while((width > crun) && (run == in[crun])) if(++crun == 129) break;
  1069.  
  1070.          if((crun > 2) || (crun == width)) { /* use this run */
  1071.  
  1072.             *out++ = (257 - crun) & 0xff; *out++ = run; used += 2;
  1073.  
  1074.             width -= crun; in    += crun;
  1075.             crun = 1;
  1076.  
  1077.          } else {                            /* ignore this run */
  1078.  
  1079.             for(cdata = crun; (width > cdata) && (crun < 4);) {
  1080.                if(run  == in[cdata]) crun += 1;
  1081.                else run = in[cdata], crun  = 1;
  1082.                if(++cdata == 128) break;
  1083.             }
  1084.  
  1085.             if(crun < 3) crun   = 0;    /* ignore trailing run */
  1086.             else         cdata -= crun;
  1087.  
  1088.             *out++ = cdata-1;     used++;
  1089.             memcpy(out,in,cdata); used += cdata; out   += cdata;
  1090.  
  1091.             width -= cdata; in    += cdata;
  1092.  
  1093.          }              /* use/ignore run */
  1094.  
  1095.       }                  /* something to compress */
  1096.  
  1097.    } else {         /* Empty scans to fill bands */
  1098.  
  1099.       while(width > 0) {
  1100.          crun   = width > 129 ? 129 : width;
  1101.          width -= crun;
  1102.          *out++ = (257 - crun) & 0xff;
  1103.          *out++ = 0;
  1104.          used  += 2;
  1105.       }
  1106.    }                /* Data present or empty */
  1107.    return used;
  1108. }
  1109.  
  1110.  
  1111. /*
  1112.  * Horizontal & vertical positioning, color-selection, "ESC ."
  1113.  */
  1114. private int 
  1115. stc_print_escpcmd(stcolor_device *sd, FILE *prn_stream,
  1116.    int escp_used, int color,int m,int wbytes)
  1117. {
  1118.  
  1119.    int dy  = sd->stc.stc_y - sd->stc.prt_y; /* number of units to skip */
  1120.    int nlf;
  1121.  
  1122. /* ESC-R color codes, used only here */
  1123.    static const byte stc_colors[] = { 0x02, 0x01, 0x04, 0x00 }; /* CMYK */
  1124.  
  1125. /*
  1126.  * initialize the printer, if necessary
  1127.  */
  1128.    if(0 == (sd->stc.flags & STCPRINT)) {
  1129.  
  1130.       fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
  1131.  
  1132.       if(0 < sd->stc.escp_lf) { /* Adjust Linefeed */
  1133.          fputc('\033',        prn_stream);
  1134.          fputc('+',           prn_stream);
  1135.          fputc(((sd->stc.escp_m*sd->stc.escp_u) / 10),prn_stream);
  1136.       }                         /* Adjust Linefeed */
  1137.       sd->stc.flags |= STCPRINT;
  1138.    }
  1139.  
  1140.    sd->stc.escp_data[escp_used++]  = '\r';     /* leftmost position */
  1141.  
  1142.    if(dy) {                                    /* position the printer */
  1143.       if(( sd->stc.escp_lf      >  0) && /* Linefeed allowed */
  1144.          ((dy % sd->stc.escp_lf) == 0))   /* and possible */
  1145.             nlf = dy / sd->stc.escp_lf;
  1146.       else  nlf = 7;
  1147.          
  1148.       if(nlf > 6) {
  1149.          sd->stc.escp_data[escp_used++]  = '\033';
  1150.          sd->stc.escp_data[escp_used++]  = '(';
  1151.          sd->stc.escp_data[escp_used++]  = 'V';
  1152.          sd->stc.escp_data[escp_used++]  = '\002';
  1153.          sd->stc.escp_data[escp_used++]  = '\000';
  1154.          sd->stc.escp_data[escp_used++]  =  sd->stc.stc_y       & 0xff;
  1155.          sd->stc.escp_data[escp_used++]  = (sd->stc.stc_y >> 8) & 0xff;
  1156.       } else {
  1157.          while(nlf--) sd->stc.escp_data[escp_used++] = '\n';
  1158.       }
  1159.       sd->stc.prt_y = sd->stc.stc_y;
  1160.    }                                           /* position the printer */
  1161.  
  1162.    if((sd->color_info.num_components > 1) &&
  1163.       (sd->stc.escp_c != stc_colors[color])) { /* select color */
  1164.        sd->stc.escp_data[escp_used++]  = '\033';
  1165.        sd->stc.escp_data[escp_used++]  = 'r';
  1166.        sd->stc.escp_c                  = stc_colors[color];
  1167.        sd->stc.escp_data[escp_used++]  = sd->stc.escp_c;
  1168.    }                                           /* select color */
  1169.  
  1170. /*
  1171.  * Build the command used
  1172.  */
  1173.    sd->stc.escp_data[escp_used++] = '\033';
  1174.    sd->stc.escp_data[escp_used++] = '.';
  1175.    sd->stc.escp_data[escp_used++] =
  1176.        (sd->stc.flags & STCCOMP) == STCPLAIN ? 0 : 1;
  1177.    sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
  1178.    sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
  1179.    sd->stc.escp_data[escp_used++] = m;
  1180.    sd->stc.escp_data[escp_used++] = (wbytes<<3) & 0xff; /* width in Pixels */
  1181.    sd->stc.escp_data[escp_used++] = (wbytes>>5) & 0xff;
  1182.  
  1183.    return escp_used;
  1184. }
  1185.  
  1186. /*
  1187.  * compute width of a group of scanlines
  1188.  */
  1189. private int 
  1190. stc_bandwidth(stcolor_device *sd,int color,int m,int npass)
  1191. {
  1192.    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
  1193.    int buf_a  = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
  1194.    int w      = 0;
  1195.  
  1196.    while(m-- > 0) { /* check width */
  1197.       if(sd->stc.prt_width[buf_a] > w) w = sd->stc.prt_width[buf_a];
  1198.       buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
  1199.    }                       /* check width */
  1200.  
  1201.    return w;
  1202. }
  1203.  
  1204. /*
  1205.  * Multi-Pass Printing-Routine
  1206.  */
  1207. private void 
  1208. stc_print_weave(stcolor_device *sd, FILE *prn_stream)
  1209. {
  1210.  
  1211.    int escp_used,nprint,nspace,color,buf_a,iprint,w;
  1212.  
  1213.    int npass  = sd->stc.escp_v / sd->stc.escp_u;
  1214.    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
  1215.  
  1216.  
  1217.    while(sd->stc.stc_y < sd->stc.prt_scans) {
  1218.  
  1219. /*
  1220.  * compute spacing & used heads (seems to work with odd escp_m)
  1221.  */
  1222.       if(sd->stc.stc_y >= sd->stc.escp_m) { /* in normal mode */
  1223.          nprint = sd->stc.escp_m;
  1224.          nspace = sd->stc.escp_m;
  1225.       } else if((sd->stc.stc_y) < npass) {                /* initialisation */
  1226.          nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
  1227.          nspace = 1;
  1228.       } else {                                   /* switch to normal */
  1229.          nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
  1230.          nspace = sd->stc.escp_m - sd->stc.stc_y;
  1231.       }
  1232.       iprint = sd->stc.stc_y + npass * nprint;
  1233.       if(sd->stc.buf_y < iprint) break;
  1234.  
  1235.       escp_used = 0;
  1236.       for(color = 0; color < ncolor; ++color) { /* print the colors */
  1237.  
  1238.          if(0 == (w = stc_bandwidth(sd,color,nprint,npass))) continue;
  1239.  
  1240.          escp_used = stc_print_escpcmd(sd,prn_stream,
  1241.                                        escp_used,color,sd->stc.escp_m,w);
  1242.  
  1243.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
  1244.          for(iprint = 0; iprint < nprint; ++iprint) { /* send data */
  1245.  
  1246.             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
  1247.                memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
  1248.                escp_used += w;
  1249.             } else {
  1250.                escp_used += stc_rle(sd->stc.escp_data+escp_used,
  1251.                                     sd->stc.prt_data[buf_a],w);
  1252.             }
  1253.  
  1254.             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
  1255.             escp_used = 0;
  1256.  
  1257.             buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
  1258.  
  1259.          }                                            /* send data */
  1260.  
  1261.          while(iprint++ < sd->stc.escp_m) {  /* add empty rows */
  1262.  
  1263.             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
  1264.                memset(sd->stc.escp_data+escp_used,0,w);
  1265.                escp_used += w;
  1266.             } else {
  1267.                escp_used += stc_rle(sd->stc.escp_data+escp_used,NULL,w);
  1268.             }
  1269.  
  1270.             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
  1271.             escp_used = 0;
  1272.          }                               /* add empty rows */
  1273.       }                                             /* print the colors */
  1274.  
  1275.       sd->stc.stc_y += nspace;
  1276.    }
  1277. }
  1278.  
  1279. /*
  1280.  * Single-Pass printing-Routine
  1281.  */
  1282. private void 
  1283. stc_print_bands(stcolor_device *sd, FILE *prn_stream)
  1284. {
  1285.  
  1286.    int escp_used,color,buf_a,iprint,w,m;
  1287.  
  1288.    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
  1289.  
  1290.    while(sd->stc.stc_y < sd->stc.prt_scans) {
  1291.  
  1292. /*
  1293.  * find the begin of the band
  1294.  */
  1295.       for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
  1296.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
  1297.          for(color = 0; color < ncolor; ++color)
  1298.             if(sd->stc.prt_width[buf_a+color] > w)
  1299.                w = sd->stc.prt_width[buf_a+color];
  1300.          if(w != 0) break;
  1301.       }
  1302.       if(w == 0) break;
  1303. /*
  1304.  * adjust the band-height
  1305.  */
  1306.       w = sd->stc.prt_scans - sd->stc.stc_y;
  1307.       if((w < sd->stc.escp_m) && (sd->stc.escp_v != 40)) {
  1308.          if(w < 8)       m =  1;
  1309.          else if(w < 24) m =  8;
  1310.          else            m = 24;
  1311.       } else {
  1312.          m = sd->stc.escp_m;
  1313.       }
  1314.  
  1315.       if(sd->stc.buf_y < (sd->stc.stc_y+m)) break;
  1316.  
  1317.       escp_used = 0;
  1318.       for(color = 0; color < ncolor; ++color) { /* print the colors */
  1319.  
  1320.          if(0 == (w = stc_bandwidth(sd,color,m,1))) continue; /* shortcut */
  1321.  
  1322.          escp_used = stc_print_escpcmd(sd,prn_stream,escp_used,color,m,w);
  1323.  
  1324.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
  1325.          for(iprint = 0; iprint < m; ++iprint) { /* send data */
  1326.  
  1327.             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
  1328.                memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
  1329.                escp_used += w;
  1330.             } else {
  1331.                escp_used += stc_rle(sd->stc.escp_data+escp_used,
  1332.                                     sd->stc.prt_data[buf_a],w);
  1333.             }
  1334.  
  1335.             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
  1336.             escp_used = 0;
  1337.  
  1338.             buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor);
  1339.  
  1340.          }                                            /* send data */
  1341.  
  1342.       }                                             /* print the colors */
  1343.  
  1344.       sd->stc.stc_y += m;
  1345.    }
  1346. }
  1347. /* ----------------------------------------------------------------------- */
  1348.  
  1349. private int 
  1350. stc_deltarow(byte *out,const byte *in,int width,byte *seed)
  1351. {
  1352.  
  1353.    int istop,nmove,ndata,i,j;
  1354.    int *wseed = (int *) seed;
  1355.    int used   = 0;
  1356.  
  1357.    seed += sizeof(int);
  1358.  
  1359.    if((in != NULL) && (width > 0)) { /* Data present */
  1360.  
  1361.       istop = width < wseed[0] ? wseed[0] : width;
  1362.  
  1363.       i = 0;
  1364.       while(i < istop) {
  1365.  
  1366.          for(j = i; j < istop; ++j) if(in[j] != seed[j]) break;
  1367.  
  1368.          nmove = j - i;
  1369.  
  1370.          if(nmove > 0) { /* issue a move */
  1371.            i     = j;
  1372.            if(i == istop) break;
  1373.  
  1374.            if(       nmove <   8) {
  1375.               out[used++] = 0x40 | nmove;
  1376.            } else if(nmove < 128) {
  1377.               out[used++] = 0x51;
  1378.               out[used++] = nmove;
  1379.            } else {
  1380.               out[used++] = 0x52;
  1381.               out[used++] = 0xff & nmove;
  1382.               out[used++] = 0xff & (nmove>>8);
  1383.            }
  1384.          }           /* issue a move */
  1385.  
  1386. /*
  1387.  * find the end of this run
  1388.  */
  1389.          nmove = 0;
  1390.          for(j = i+1; (j < istop) && ((nmove < 4)); ++j) {
  1391.             if(in[j] == seed[j]) nmove += 1;
  1392.             else                 nmove  = 0;
  1393.          }
  1394.  
  1395.          ndata = j-i-nmove;
  1396.  
  1397.          nmove = stc_rle(out+used+3,in+i,ndata);
  1398.          if(nmove < 16) {
  1399.             out[used++] = 0x20 | nmove;
  1400.             for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+2];
  1401.          } else if(nmove < 256) {
  1402.             out[used++] = 0x31;
  1403.             out[used++] = nmove;
  1404.             for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+1];
  1405.          } else {
  1406.             out[used++] = 0x32;
  1407.             out[used++] = 0xff & nmove;
  1408.             out[used++] = 0xff & (nmove>>8);
  1409.          }
  1410.          used += nmove;
  1411.          i    += ndata;
  1412.       }
  1413.  
  1414.       memcpy(seed,in,istop);
  1415.       wseed[0] = width;
  1416.  
  1417.    } else if(wseed[0] > 0) { /* blank line, but seed has data */
  1418.  
  1419.       out[used++] = 0xe1; /* clear row */
  1420.       memset(seed,0,wseed[0]);
  1421.       wseed[0] = 0;
  1422.  
  1423.    }
  1424.  
  1425.    return used;
  1426. }
  1427.  
  1428. /*
  1429.  * Slightly different single-pass printing
  1430.  */
  1431. private void
  1432. stc_print_delta(stcolor_device *sd, FILE *prn_stream)
  1433. {
  1434.  
  1435.    int color,buf_a,w;
  1436.    int escp_used = 0; 
  1437.    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
  1438.  
  1439.    while(sd->stc.stc_y < sd->stc.prt_scans) {
  1440.  
  1441. /*
  1442.  * find the begin of the band
  1443.  */
  1444.       for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
  1445.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
  1446.          for(color = 0; color < ncolor; ++color)
  1447.             if(sd->stc.prt_width[buf_a+color] > w)
  1448.                w = sd->stc.prt_width[buf_a+color];
  1449.          if(w != 0) break;
  1450.       }
  1451.  
  1452.       if(sd->stc.buf_y == sd->stc.stc_y) break;
  1453.  
  1454.       escp_used = 0;
  1455.  
  1456. /*
  1457.  * Send Initialization & ESC . 3 once
  1458.  */
  1459.       if(0 == (sd->stc.flags & STCPRINT)) {
  1460.  
  1461.          sd->stc.flags |= STCPRINT;
  1462.  
  1463.          fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
  1464.  
  1465.          sd->stc.escp_data[escp_used++] = '\033';
  1466.          sd->stc.escp_data[escp_used++] = '.';
  1467.          sd->stc.escp_data[escp_used++] =  3;
  1468.          sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
  1469.          sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
  1470.          sd->stc.escp_data[escp_used++] = sd->stc.escp_m;
  1471.          sd->stc.escp_data[escp_used++] = 0;
  1472.          sd->stc.escp_data[escp_used++] = 0;
  1473.          sd->stc.escp_data[escp_used++] = 0xe4; /* MOVXBYTE */
  1474.       }
  1475.  
  1476.       if(sd->stc.stc_y != sd->stc.prt_y) { /* really position the printer */
  1477.          w = sd->stc.stc_y - sd->stc.prt_y;
  1478.          if(       w <  16) {
  1479.             sd->stc.escp_data[escp_used++] = 0x60 | w;
  1480.          } else if(w < 256) {
  1481.             sd->stc.escp_data[escp_used++] = 0x71;
  1482.             sd->stc.escp_data[escp_used++] = w;
  1483.          } else {
  1484.             sd->stc.escp_data[escp_used++] = 0x72;
  1485.             sd->stc.escp_data[escp_used++] = 0xff & w;
  1486.             sd->stc.escp_data[escp_used++] = 0xff & (w>>8);
  1487.          }
  1488.          sd->stc.prt_y = sd->stc.stc_y;
  1489.       }                                    /* really position the printer */
  1490.  
  1491.       for(color = 0; color < ncolor; ++color) { /* print the colors */
  1492.  
  1493. /* Color-Selection */
  1494.          if(color == (ncolor-1)) {
  1495.             sd->stc.escp_data[escp_used++] = 0x80; /* Black */
  1496.          } else {
  1497.             switch(color) {
  1498.             case 1:  sd->stc.escp_data[escp_used++] = 0x81; break; /* M */
  1499.             case 2:  sd->stc.escp_data[escp_used++] = 0x84; break; /* Y */
  1500.             default: sd->stc.escp_data[escp_used++] = 0x82; break; /* C */
  1501.             }
  1502.          }
  1503.  
  1504. /* Data-Transfer */
  1505.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
  1506.  
  1507.          w = stc_deltarow(sd->stc.escp_data+escp_used,
  1508.              sd->stc.prt_data[buf_a],sd->stc.prt_width[buf_a],
  1509.              sd->stc.seed_row[color]);
  1510.  
  1511.          if(w == 0) escp_used -= 1;
  1512.          else       escp_used += w;
  1513.  
  1514.          if(escp_used > 0) fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
  1515.          escp_used = 0;
  1516.  
  1517.       }                                             /* print the colors */
  1518.  
  1519.       sd->stc.stc_y += 1;
  1520.  
  1521.    }
  1522.  
  1523. }
  1524.  
  1525. /* ----------------------------------------------------------------------- */
  1526.  
  1527. /***
  1528.  *** Free-Data: release the specific-Arrays
  1529.  ***/
  1530. private void 
  1531. stc_freedata(stc_t *stc)
  1532. {
  1533.    int i,j;
  1534.  
  1535.    for(i = 0; i < 4; ++i) {
  1536.       if(stc->code[i] != NULL) {
  1537.  
  1538.          for(j = 0; j < i; ++j) if(stc->code[i] == stc->code[j]) break;
  1539.  
  1540.          if(i == j) gs_free(stc->code[i],1<<stc->bits,sizeof(gx_color_value),
  1541.                            "stcolor/code");
  1542.       }
  1543.  
  1544.       if(stc->vals[i] != NULL) {
  1545.  
  1546.          for(j = 0; j < i; ++j)
  1547.             if(stc->vals[i] == stc->vals[j]) break;
  1548.  
  1549.          if(i == j) gs_free(stc->vals[i],1<<stc->bits,sd->stc.alg_item,
  1550.                            "stcolor/transfer");
  1551.       }
  1552.    }
  1553.  
  1554.    for(i = 0; i < 4; ++i) {
  1555.       stc->code[i] = NULL;
  1556.       stc->vals[i] = NULL;
  1557.    }
  1558. }
  1559.  
  1560. /***
  1561.  *** open the device and initialize margins & arrays
  1562.  ***/
  1563.  
  1564. private int 
  1565. stc_open(gx_device *pdev) /* setup margins & arrays */
  1566. {
  1567.   stcolor_device *sd = (stcolor_device *) pdev;
  1568.   int i,j,code;
  1569.   gx_color_index white;
  1570.   byte *bpw,*bpm;
  1571.  
  1572.   code = 0;
  1573. /*
  1574.  * Establish Algorithm-Table, if not present
  1575.  */
  1576.   if(sd->stc.algorithms.size == 0) {
  1577.      gs_param_string *dp;
  1578.      for(i = 0; stc_dither[i].name != NULL; ++i); /* count 'em */
  1579.      sd->stc.algorithms.size = i;
  1580.      dp = gs_malloc(i,sizeof(gs_param_string),
  1581.                                         "stcolor/algorithms");
  1582.      if(dp == NULL) {
  1583.         code = gs_error_VMerror;
  1584.         sd->stc.algorithms.size = 0;
  1585.      } else {
  1586.         sd->stc.algorithms.data       = dp;
  1587.         sd->stc.algorithms.persistent = true;
  1588.         for(i = 0; stc_dither[i].name != NULL; ++i) {
  1589.         param_string_from_string(dp[i],stc_dither[i].name);
  1590.         }
  1591.      }
  1592.   }
  1593.  
  1594. # define stc_sizeofitem(T) sd->stc.alg_item = sizeof(T)
  1595.   STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
  1596.  
  1597.   stc_print_setup(sd);
  1598.  
  1599. /*
  1600.  * Establish internal Value & Code-Arrays
  1601.  */
  1602.  
  1603.  
  1604.   for(i = 0; i < sd->color_info.num_components; ++i) { /* comp */
  1605.  
  1606.      if((sd->stc.sizc[i] >  1) && (sd->stc.extc[i] != NULL)) { /* code req. */
  1607.  
  1608.         for(j = 0; j < i; ++j) if(sd->stc.extc[i] == sd->stc.extc[j]) break;
  1609.  
  1610.         if(i == j) { /* new one */
  1611.            sd->stc.code[i] = gs_malloc(1<<sd->stc.bits,sizeof(gx_color_value),
  1612.                              "stcolor/code");
  1613.  
  1614.            if(sd->stc.code[i] == NULL) { /* error */
  1615.               code = gs_error_VMerror;
  1616.            } else {                      /* success */
  1617. /*
  1618.  * Try making things easier:
  1619.  *     normalize values to 0.0/1.0-Range
  1620.  *     X-Axis:   Color-Values (implied)
  1621.  *     Y-Values: Indices      (given)
  1622.  */
  1623.               unsigned long ly,iy;
  1624.               double ystep,xstep,fx,fy;
  1625.  
  1626. /* normalize */
  1627.  
  1628.               fx =  1e18;
  1629.               fy = -1e18;
  1630.               for(ly = 0; ly < sd->stc.sizc[i]; ++ly) {
  1631.                  if(sd->stc.extc[i][ly] < fx) fx = sd->stc.extc[i][ly];
  1632.                  if(sd->stc.extc[i][ly] > fy) fy = sd->stc.extc[i][ly];
  1633.               }
  1634.               if((fx != 0.0) || (fy != 1.0)) {
  1635.                  fy = 1.0 / (fy - fx);
  1636.                  for(ly = 0; ly < sd->stc.sizc[i]; ++ly)
  1637.                     sd->stc.extc[i][ly] = fy * (sd->stc.extc[i][ly]-fx);
  1638.               }
  1639.  
  1640. /* interpolate */
  1641.               ystep = 1.0 / (double)((1<<sd->stc.bits)-1);
  1642.               xstep = 1.0 / (double)( sd->stc.sizc[i] -1);
  1643.  
  1644.               iy = 0;
  1645.               for(ly = 0; ly < (1<<sd->stc.bits); ++ly) {
  1646.                  fy = ystep * ly;
  1647.                  while(((iy+1) < sd->stc.sizc[i]) &&
  1648.                        (  fy   > sd->stc.extc[i][iy+1])) ++iy;
  1649.                  fx  = iy + (fy - sd->stc.extc[i][iy])
  1650.                             / (sd->stc.extc[i][iy+1] - sd->stc.extc[i][iy]);
  1651.                  fx *= xstep * gx_max_color_value;
  1652.  
  1653.                  fx = fx < 0.0 ? 0.0 :
  1654.                       (fx > gx_max_color_value ? gx_max_color_value : fx);
  1655.  
  1656.                  sd->stc.code[i][ly] = fx;
  1657.                  if((fx-sd->stc.code[i][ly]) >= 0.5) sd->stc.code[i][ly] += 1;
  1658.               }
  1659.            }                             /* error || success */
  1660.  
  1661.         } else {     /* shared one */
  1662.  
  1663.            sd->stc.code[i] = sd->stc.code[j];
  1664.  
  1665.         }           /* new || shared one */
  1666.      }                                                         /* code req. */
  1667.  
  1668.      if((sd->stc.sizv[i] >  1) && (sd->stc.extv[i] != NULL)) { /* vals req. */
  1669.  
  1670.         for(j = 0; j < i; ++j)
  1671.            if((sd->stc.extc[i] == sd->stc.extc[j]) &&
  1672.               (sd->stc.extv[i] == sd->stc.extv[j])) break;
  1673.  
  1674.         if(i == j) { /* new one */
  1675.  
  1676.              sd->stc.vals[i] =
  1677.                 gs_malloc(1<<sd->stc.bits,sd->stc.alg_item,"stcolor/transfer");
  1678.  
  1679.            if(sd->stc.vals[i] == NULL) {
  1680.  
  1681.               code = gs_error_VMerror;
  1682.  
  1683.            } else {                      /* success */
  1684.  
  1685.  
  1686.               if(sd->stc.code[i] == NULL) { /* linear */
  1687.  
  1688.                  byte  *Out  = sd->stc.vals[i];
  1689.                  int    Nout = 1<<sd->stc.bits;
  1690.                  double Omin = sd->stc.dither->minmax[0];
  1691.                  double Omax = sd->stc.dither->minmax[1];
  1692.                  float *In   = sd->stc.extv[i];
  1693.                  int    Nin  = sd->stc.sizv[i];
  1694.                  unsigned long I,io;
  1695.                  double Istep,Ostep,Y;
  1696.                  byte   Ovb; long Ovl;
  1697.  
  1698.                  Istep = 1.0 / (double) ((Nin)-1);
  1699.                  Ostep = 1.0 / (double) ((Nout)-1);
  1700.  
  1701.                  for(io = 0; io < (Nout); ++io) {
  1702.                     I = (long)(io * ((Nin)-1))/((Nout)-1);
  1703.  
  1704.                     if((I+1) < (Nin))
  1705.                        Y = In[I] + (In[I+1]-In[I])
  1706.                                      * ((double) io * Ostep - (double)I * Istep)
  1707.                                                /  (double) Istep;
  1708.                     else
  1709.                        Y = In[I] + (In[I]-In[I-1])
  1710.                                      * ((double) io * Ostep - (double)I * Istep)
  1711.                                                /  (double) Istep;
  1712.  
  1713.                     Y = Omin + (Omax-Omin) * Y;
  1714.                     Y = Y < Omin ? Omin : (Y > Omax ? Omax : Y);
  1715.  
  1716.  
  1717.                     switch(sd->stc.dither->flags & STC_TYPE) {
  1718.                        case STC_BYTE:
  1719.                           Ovb = Y;
  1720.                           if(((Y-Ovb) >= 0.5) && ((Ovb+1) <= Omax)) Ovb += 1;
  1721.                           Out[io] = Ovb;
  1722.                           break;
  1723.                        case STC_LONG:
  1724.                           Ovl = Y;
  1725.                           if(((Y-Ovl) >= 0.5) && ((Ovl+1) <= Omax)) Ovl += 1;
  1726.                           if(((Ovl-Y) >= 0.5) && ((Ovl-1) >= Omax)) Ovl -= 1;
  1727.                           ((long *)Out)[io] = Ovl;
  1728.                           break;
  1729.                        default:
  1730.                           ((float *)Out)[io] = Y;
  1731.                           break;
  1732.                     }
  1733.                  }
  1734.  
  1735.               } else {                     /* encoded */
  1736.                  unsigned long j,o;
  1737.                  double xstep,x,y;
  1738.  
  1739.                  xstep = 1.0 / (double) (sd->stc.sizv[i]-1);
  1740.  
  1741. /*
  1742.  * The following differs in so far from the previous, that the desired
  1743.  * X-Values are stored in another array.
  1744.  */
  1745.                  for(o = 0; o < (1<<sd->stc.bits); ++o) { /* code-loop */
  1746.  
  1747.                     x = sd->stc.code[i][o]; x /= gx_max_color_value;
  1748.  
  1749.                     j = x / xstep;
  1750.  
  1751.                     if((j+1) < sd->stc.sizv[i]) {
  1752.                        y  = sd->stc.extv[i][j];
  1753.                        y += (sd->stc.extv[i][j+1]-y)*(x-(double)j*xstep)/xstep;
  1754.                     } else {
  1755.                        y  = sd->stc.extv[i][j];
  1756.                        y += (y-sd->stc.extv[i][j-1])*(x-(double)j*xstep)/xstep;
  1757.                     }
  1758.  
  1759.                     y = sd->stc.dither->minmax[0]
  1760.                       +(sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0])*y;
  1761.  
  1762. #                   define stc_adjvals(T)                                             \
  1763.                      ((T *)(sd->stc.vals[i]))[o] = y;                                 \
  1764.                                                                                       \
  1765.                     if(((y-((T *)(sd->stc.vals[i]))[o]) >= 0.5) &&                    \
  1766.                        ((1+((T *)(sd->stc.vals[i]))[o]) <= sd->stc.dither->minmax[1]))\
  1767.                        ((T *)(sd->stc.vals[i]))[o]      += 1;                         \
  1768.                                                                                       \
  1769.                     if(((((T *)(sd->stc.vals[i]))[o]-y) >= 0.5) &&                    \
  1770.                        ((((T *)(sd->stc.vals[i]))[o]-1) >= sd->stc.dither->minmax[0]))\
  1771.                        ((T *)(sd->stc.vals[i]))[o]      -= 1;
  1772.  
  1773.                     STC_TYPESWITCH(sd->stc.dither,stc_adjvals)
  1774.  
  1775. #                   undef stc_adjvals
  1776.                  }                                       /* code-loop */
  1777.               }                            /* lineaer / encoded */
  1778.            }                             /* error || success */
  1779.  
  1780.         } else {     /* shared one */
  1781.  
  1782.            sd->stc.vals[i] = sd->stc.vals[j];
  1783.  
  1784.         }           /* new || shared one */
  1785.      }                                                         /* vals req. */
  1786.   }                                                    /* comp */
  1787.  
  1788.   if(code == 0) {
  1789.  
  1790.       sd->stc.flags |= STCOK4GO;
  1791.  
  1792. /*
  1793.  * Arrgh: open-procedure seems to be the right-place, but it is
  1794.  *        necessary to establish the defaults for omitted procedures too.
  1795.  */
  1796.  
  1797.       switch(sd->color_info.num_components) { /* Establish color-procs */
  1798.       case 1:
  1799.          set_dev_proc(sd,map_rgb_color, stc_map_gray_color);
  1800.          set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
  1801.          set_dev_proc(sd,map_color_rgb, stc_map_color_gray);
  1802.          white = stc_map_gray_color((gx_device *) sd,
  1803.                     gx_max_color_value,gx_max_color_value,gx_max_color_value);
  1804.          break;
  1805.       case 3:
  1806.          set_dev_proc(sd,map_rgb_color, stc_map_rgb_color);
  1807.          set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
  1808.          set_dev_proc(sd,map_color_rgb, stc_map_color_rgb);
  1809.          white = stc_map_rgb_color((gx_device *) sd,
  1810.                     gx_max_color_value,gx_max_color_value,gx_max_color_value);
  1811.          break;
  1812.       default:
  1813.          set_dev_proc(sd,map_rgb_color, gx_default_map_rgb_color);
  1814.          if(sd->stc.flags & STCCMYK10) {
  1815.             set_dev_proc(sd,map_cmyk_color,stc_map_cmyk10_color);
  1816.             set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk10);
  1817.             white = stc_map_cmyk10_color((gx_device *) sd,0,0,0,0);
  1818.          } else {
  1819.             set_dev_proc(sd,map_cmyk_color,stc_map_cmyk_color);
  1820.             set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk);
  1821.             white = stc_map_cmyk_color((gx_device *) sd,0,0,0,0);
  1822.          }
  1823.          break;                               /* Establish color-procs */
  1824.       }
  1825.  
  1826.  
  1827. /*
  1828.  * create at least a Byte
  1829.  */
  1830.       if(sd->color_info.depth < 2) white |= (white<<1);
  1831.       if(sd->color_info.depth < 4) white |= (white<<2);
  1832.       if(sd->color_info.depth < 8) white |= (white<<4);
  1833.  
  1834. /*
  1835.  * copy the Bytes
  1836.  */
  1837.       bpw = (byte *) sd->stc.white_run;
  1838.  
  1839.       if(sd->color_info.depth < 16) {
  1840.          for(i = 0; i < sizeof(sd->stc.white_run); i += 1) {
  1841.             bpw[i] = 0xff & white;
  1842.          }
  1843.       } else if(sd->color_info.depth < 24) {
  1844.          for(i = 0; i < sizeof(sd->stc.white_run); i += 2) {
  1845.             bpw[i]   = 0xff & (white>>8);
  1846.             bpw[i+1] = 0xff &  white;
  1847.          }
  1848.       } else if(sd->color_info.depth < 32) {
  1849.          for(i = 0; i < sizeof(sd->stc.white_run); i += 3) {
  1850.             bpw[i]   = 0xff & (white>>16);
  1851.             bpw[i+1] = 0xff & (white>> 8);
  1852.             bpw[i+2] = 0xff &  white;
  1853.          }
  1854.       } else {
  1855.          for(i = 0; i < sizeof(sd->stc.white_run); i += 4) {
  1856.             bpw[i]   = 0xff & (white>>24);
  1857.             bpw[i+1] = 0xff & (white>>16);
  1858.             bpw[i+2] = 0xff & (white>> 8);
  1859.             bpw[i+3] = 0xff &  white;
  1860.          }
  1861.       }
  1862. /*
  1863.  *    compute the trailer
  1864.  */
  1865.       j  = sd->width -
  1866.           (dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch;
  1867.       j  = j * sd->color_info.depth;            /* the Bit-count */
  1868.       j  = j % (32*countof(sd->stc.white_run)); /* remaining Bits */
  1869.  
  1870.       bpm = (byte *) sd->stc.white_end;
  1871.       for(i = 0; i < (4*countof(sd->stc.white_end)); ++i) {
  1872.          if(       j <= 0) {
  1873.             bpm[i] = 0;
  1874.          } else if(j >= 8) {
  1875.             bpm[i] = 0xff;
  1876.             j -= 8;
  1877.          } else {
  1878.             bpm[i] = 0xff ^ ((1<<(8-j))-1);
  1879.             j  = 0;
  1880.          }
  1881.          bpm[i] &= bpw[i];
  1882.       }
  1883.  
  1884. /*
  1885.  * Call super-class open
  1886.  */
  1887.  
  1888.       return gdev_prn_open(pdev);
  1889.  
  1890.    } else {
  1891.  
  1892.       stc_freedata(&sd->stc);
  1893.  
  1894.       return_error(code);
  1895.    }
  1896.  
  1897. }
  1898.  
  1899. /***
  1900.  *** stc_close: release the internal data
  1901.  ***/
  1902. private int 
  1903. stc_close(gx_device *pdev)
  1904. {
  1905.    stc_freedata(&((stcolor_device *) pdev)->stc);
  1906.    ((stcolor_device *) pdev)->stc.flags &= ~STCOK4GO;
  1907.    return gdev_prn_close(pdev);
  1908. }
  1909.  
  1910.  
  1911. /***
  1912.  *** Function for Bit-Truncation, including direct-byte-transfer
  1913.  ***/
  1914. private gx_color_value 
  1915. stc_truncate(stcolor_device *sd,int i,gx_color_value v)
  1916. {
  1917.  
  1918.    if(sd->stc.bits < gx_color_value_bits) {
  1919.       if(sd->stc.code[i] != NULL) {
  1920. /*
  1921.  * Perform binary search in the code-array
  1922.  */
  1923.          long  s;
  1924.          gx_color_value *p;
  1925.  
  1926.          s = sd->stc.bits > 1 ? 1L<<(sd->stc.bits-2) : 0L;
  1927.          p = sd->stc.code[i]+(1L<<(sd->stc.bits-1));
  1928.  
  1929.          while(s > 0) {
  1930.             if(v > *p) {
  1931.                p += s;
  1932.             } else if(v < p[-1]) {
  1933.                p -= s;
  1934.             } else {
  1935.                if((v-p[-1]) < (p[0]-v)) p -= 1;
  1936.                break;
  1937.             }
  1938.             s >>= 1;
  1939.          }
  1940.          if((v-p[-1]) < (p[0]-v)) p -= 1;
  1941.          v = p - sd->stc.code[i];
  1942.  
  1943.       } else {
  1944.  
  1945.          v >>= gx_color_value_bits-sd->stc.bits;
  1946.  
  1947.       }
  1948.  
  1949. /*
  1950.       V = (((1L<<D->stc.bits)-1)*V+(gx_max_color_value>>1))\
  1951.           /gx_max_color_value;                             \
  1952. */
  1953.    }
  1954.    return v;
  1955. }
  1956.  
  1957. private gx_color_value
  1958. stc_truncate1(stcolor_device *sd,int i,gx_color_value v)
  1959. {
  1960.  
  1961.    return sd->stc.vals[i][stc_truncate(sd,i,v)];
  1962. }
  1963.  
  1964. /***
  1965.  *** Expansion of indices for reverse-mapping
  1966.  ***/
  1967. private gx_color_value 
  1968. stc_expand(stcolor_device *sd,int i,gx_color_index col)
  1969. {
  1970.  
  1971.    gx_color_index cv;
  1972.    gx_color_index l = (1<<sd->stc.bits)-1;
  1973.  
  1974.    if(sd->stc.code[i] != NULL) {
  1975.  
  1976.       cv  = sd->stc.code[i][col & l];
  1977.  
  1978.    } else if(sd->stc.bits < gx_color_value_bits) {
  1979.  
  1980.       cv  = (col & l)<<(gx_color_value_bits-sd->stc.bits);
  1981.       cv += (col & l)/l * ((1<<(gx_color_value_bits-sd->stc.bits))-1);
  1982.  
  1983.    } else if(sd->stc.bits > gx_color_value_bits) {
  1984.  
  1985.       cv  = (col & l)>>(sd->stc.bits-gx_color_value_bits);
  1986.  
  1987.    } else {
  1988.  
  1989.       cv  = col & l;
  1990.  
  1991.    }
  1992.  
  1993.    return cv;
  1994. }
  1995.  
  1996. /***
  1997.  *** color-mapping of gray-scales
  1998.  ***/
  1999. private gx_color_index 
  2000. stc_map_gray_color(gx_device *pdev,
  2001.         gx_color_value r, gx_color_value g, gx_color_value b)
  2002. {
  2003.  
  2004.    stcolor_device *sd = (stcolor_device *) pdev;
  2005.    gx_color_index rv;
  2006.  
  2007.    if((r == g) && (g == b)) {
  2008.  
  2009.       rv = gx_max_color_value - r;
  2010.  
  2011.    } else if(sd->stc.am != NULL) {
  2012.       float *m,fv;
  2013.  
  2014.       m   = sd->stc.am;
  2015.  
  2016.       fv  = gx_max_color_value;
  2017.       fv -= *m++ * (float) r; fv -= *m++ * (float) g; fv -= *m   * (float) b;
  2018.  
  2019.       if(     fv < 0.0)                      rv = 0;
  2020.       else if((fv+0.5) > gx_max_color_value) rv = gx_max_color_value;
  2021.       else                                   rv = fv+0.5;
  2022.  
  2023.    } else {
  2024.  
  2025.       rv  = ((gx_color_index)gx_max_color_value)<<3;
  2026.       rv -= (gx_color_index) 3 * r;
  2027.       rv -= (gx_color_index) 3 * g;
  2028.       rv -= ((gx_color_index)b)<<1;
  2029.       rv  = (rv+4)>>3;
  2030.       if(rv > gx_max_color_value) rv = gx_max_color_value;
  2031.  
  2032.    }
  2033.  
  2034.    if(( sd->stc.bits                      ==    8) &&
  2035.       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE))
  2036.       rv = stc_truncate1(sd,0,(gx_color_value)rv);
  2037.    else
  2038.       rv =  stc_truncate(sd,0,(gx_color_value)rv);
  2039.  
  2040.    return rv;
  2041. }
  2042.  
  2043. private int 
  2044. stc_map_color_gray(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
  2045. {
  2046.    stcolor_device *sd = (stcolor_device *) pdev;
  2047.    gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
  2048.  
  2049.    prgb[0] = gx_max_color_value - stc_expand(sd,0,color & l);
  2050.    prgb[1] = prgb[0]; prgb[2] = prgb[0];
  2051.  
  2052.    return 0;
  2053. }
  2054.  
  2055. /***
  2056.  *** color-mapping of rgb-values
  2057.  ***/
  2058. private gx_color_index 
  2059. stc_map_rgb_color(gx_device *pdev,
  2060.                   gx_color_value r, gx_color_value g, gx_color_value b)
  2061. {
  2062.  
  2063.    stcolor_device *sd = (stcolor_device *) pdev;
  2064.    int          shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
  2065.    gx_color_index  rv = 0;
  2066.  
  2067.    if((sd->stc.am != NULL) && ((r != g) || (g != b))) {
  2068.       float *m,fr,fg,fb,fv;
  2069.  
  2070.       m  = sd->stc.am;
  2071.       fr = r; fg = g; fb = b;
  2072.  
  2073.       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
  2074.  
  2075.       if(     fv < 0.0)                      r = 0;
  2076.       else if((fv+0.5) > gx_max_color_value) r = gx_max_color_value;
  2077.       else                                   r = fv+0.5;
  2078.  
  2079.       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
  2080.  
  2081.       if(     fv < 0.0)                      g = 0;
  2082.       else if((fv+0.5) > gx_max_color_value) g = gx_max_color_value;
  2083.       else                                   g = fv+0.5;
  2084.  
  2085.       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
  2086.  
  2087.       if(     fv < 0.0)                      b = 0;
  2088.       else if((fv+0.5) > gx_max_color_value) b = gx_max_color_value;
  2089.       else                                   b = fv+0.5;
  2090.  
  2091.    }
  2092.  
  2093.    if(( sd->stc.bits                      ==    8) &&
  2094.       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
  2095.       rv =               stc_truncate1(sd,0,r);
  2096.       rv = (rv<<shift) | stc_truncate1(sd,1,g);
  2097.       rv = (rv<<shift) | stc_truncate1(sd,2,b);
  2098.    } else {
  2099.       rv =                stc_truncate(sd,0,r);
  2100.       rv = (rv<<shift) |  stc_truncate(sd,1,g);
  2101.       rv = (rv<<shift) |  stc_truncate(sd,2,b);
  2102.    }
  2103.  
  2104.    return rv;
  2105. }
  2106.  
  2107. private int 
  2108. stc_map_color_rgb(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
  2109. {
  2110.  
  2111.    stcolor_device *sd = (stcolor_device *) pdev;
  2112.    int          shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
  2113.    gx_color_index l =   ((gx_color_index)1<<sd->stc.bits)-1;
  2114.  
  2115.    prgb[0] = stc_expand(sd,0,((color>>(shift<<1)) & l));
  2116.    prgb[1] = stc_expand(sd,1,((color>> shift    ) & l));
  2117.    prgb[2] = stc_expand(sd,2,( color              & l));
  2118.  
  2119.    return 0;
  2120. }
  2121.  
  2122. /***
  2123.  *** color-mapping of cmyk-values
  2124.  ***/
  2125. private gx_color_index 
  2126. stc_map_cmyk_color(gx_device *pdev,
  2127.         gx_color_value c, gx_color_value m, gx_color_value y,gx_color_value k)
  2128. {
  2129.  
  2130.    stcolor_device *sd = (stcolor_device *) pdev;
  2131.    int          shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
  2132.    gx_color_index rv = 0;
  2133.  
  2134.    if((c == m) && (m == y)) {
  2135.  
  2136.       k = c > k ? c : k;
  2137.       c = m = y = 0;
  2138.  
  2139.       if(( sd->stc.bits                      ==    8) &&
  2140.       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
  2141.          k  = stc_truncate1(sd,3,k);
  2142.       } else {
  2143.          k  =  stc_truncate(sd,3,k);
  2144.       }
  2145.  
  2146.    } else {
  2147.  
  2148.       if(sd->stc.am != NULL) {
  2149.  
  2150.          float *a,fc,fm,fy,fk,fv;
  2151.  
  2152.          if(k == 0) { /* no separated black yet */
  2153.             k  = c < m ? c : m;
  2154.             k  = k < y ? k : y;
  2155.             if(k) { /* no black at all */
  2156.                c -= k;
  2157.                m -= k;
  2158.                y -= k;
  2159.            }       /* no black at all */
  2160.          }            /* no separated black yet */
  2161.  
  2162.          a  = sd->stc.am;
  2163.          fc = c; fm = m; fy = y; fk = k;
  2164.  
  2165.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2166.          if(     fv < 0.0)                      c = 0;
  2167.          else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
  2168.          else                                   c = fv+0.5;
  2169.  
  2170.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2171.          if(     fv < 0.0)                      m = 0;
  2172.          else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
  2173.          else                                   m = fv+0.5;
  2174.  
  2175.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2176.          if(     fv < 0.0)                      y = 0;
  2177.          else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
  2178.          else                                   y = fv+0.5;
  2179.  
  2180.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2181.          if(     fv < 0.0)                      k = 0;
  2182.          else if((fv+0.5) > gx_max_color_value) k = gx_max_color_value;
  2183.          else                                   k = fv+0.5;
  2184.  
  2185.       } else if(k == 0) {
  2186.  
  2187.          k  = c < m ? c : m;
  2188.          k  = k < y ? k : y;
  2189.       }
  2190.  
  2191.       if(( sd->stc.bits                      ==    8) &&
  2192.          ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
  2193.          c = stc_truncate1(sd,0,c);
  2194.          m = stc_truncate1(sd,1,m);
  2195.          y = stc_truncate1(sd,2,y);
  2196.          k = stc_truncate1(sd,3,k);
  2197.       } else {
  2198.          c = stc_truncate(sd,0,c);
  2199.          m = stc_truncate(sd,1,m);
  2200.          y = stc_truncate(sd,2,y);
  2201.          k = stc_truncate(sd,3,k);
  2202.       }
  2203.    }
  2204.  
  2205.    rv =               c;
  2206.    rv = (rv<<shift) | m;
  2207.    rv = (rv<<shift) | y;
  2208.    rv = (rv<<shift) | k;
  2209.  
  2210.    if(rv == gx_no_color_index) rv ^= 1;
  2211.  
  2212.    return rv;
  2213. }
  2214.  
  2215. private int 
  2216. stc_map_color_cmyk(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
  2217. {
  2218.  
  2219.    stcolor_device *sd = (stcolor_device *) pdev;
  2220.    int          shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
  2221.    gx_color_index   l = ((gx_color_index)1<<sd->stc.bits)-1;
  2222.    gx_color_value c,m,y,k;
  2223.  
  2224.    k = stc_expand(sd,3, color & l); color >>= shift;
  2225.    y = stc_expand(sd,2, color & l); color >>= shift;
  2226.    m = stc_expand(sd,1, color & l); color >>= shift;
  2227.    c = stc_expand(sd,0, color & l);
  2228.  
  2229.    if((c == m) && (m == y)) {
  2230.       prgb[0] = gx_max_color_value-k;
  2231.       prgb[1] = prgb[0];
  2232.       prgb[2] = prgb[0];
  2233.    } else {
  2234.       prgb[0] = gx_max_color_value-c;
  2235.       prgb[1] = gx_max_color_value-m;
  2236.       prgb[2] = gx_max_color_value-y;
  2237.    }
  2238.    return 0;
  2239. }
  2240.  
  2241. /***
  2242.  *** color-mapping of cmyk10-values
  2243.  ***/
  2244. private gx_color_index 
  2245. stc_map_cmyk10_color(gx_device *pdev,
  2246.         gx_color_value c, gx_color_value m, gx_color_value y,gx_color_value k)
  2247. {
  2248.  
  2249.    stcolor_device *sd = (stcolor_device *) pdev;
  2250.    int             mode;
  2251.    gx_color_index rv  = 0;
  2252.  
  2253.    if((c == m) && (m == y)) {
  2254.  
  2255.       k = c > k ? c : k;
  2256.       c = m = y = 0;
  2257.       mode = 3;
  2258.  
  2259.    } else {
  2260.  
  2261.       if(sd->stc.am != NULL) {
  2262.  
  2263.          float *a,fc,fm,fy,fk,fv;
  2264.  
  2265.          k  = c < m ? c : m;
  2266.          k  = k < y ? k : y;
  2267.          if(k) { /* no black at all */
  2268.             c -= k;
  2269.             m -= k;
  2270.             y -= k;
  2271.          }       /* no black at all */
  2272.  
  2273.          a  = sd->stc.am;
  2274.          fc = c; fm = m; fy = y; fk = k;
  2275.  
  2276.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2277.          if(     fv < 0.0)                      c = 0;
  2278.          else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
  2279.          else                                   c = fv+0.5;
  2280.  
  2281.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2282.          if(     fv < 0.0)                      m = 0;
  2283.          else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
  2284.          else                                   m = fv+0.5;
  2285.  
  2286.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2287.          if(     fv < 0.0)                      y = 0;
  2288.          else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
  2289.          else                                   y = fv+0.5;
  2290.  
  2291.       }
  2292.  
  2293.       if(c < m) {
  2294.         if(c < y) { k = c; c = 0; mode = 0; }
  2295.         else      { k = y; y = 0; mode = 2; }
  2296.       } else {
  2297.         if(m < y) { k = m; m = 0; mode = 1; }
  2298.         else      { k = y; y = 0; mode = 2; }
  2299.       }
  2300.    }
  2301.  
  2302. /*
  2303.  * truncate only the values that require it
  2304.  */
  2305.    if(c) c = stc_truncate(sd,0,c);
  2306.    if(m) m = stc_truncate(sd,1,m);
  2307.    if(y) y = stc_truncate(sd,2,y);
  2308.    if(k) k = stc_truncate(sd,3,k);
  2309.  
  2310. /*
  2311.  * make sure that truncation-white becomes white.
  2312.  */
  2313.    if((c|m|y) == 0) mode = 3;
  2314.  
  2315. /*
  2316.  * check wether value-arrays can be bypassed
  2317.  */
  2318.    if(((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
  2319.       ( sd->stc.dither->minmax[0]         ==    0.0 )) {
  2320.       c = sd->stc.vals[0][c];
  2321.       m = sd->stc.vals[1][m];
  2322.       y = sd->stc.vals[2][y];
  2323.       k = sd->stc.vals[3][k];
  2324.    } else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
  2325.              ( sd->stc.dither->minmax[0]         ==     0.0 ) &&
  2326.              ( sd->stc.dither->minmax[1]         <=  1023.0 )) {
  2327.       c = ((long *)(sd->stc.vals[0]))[c];
  2328.       m = ((long *)(sd->stc.vals[1]))[m];
  2329.       y = ((long *)(sd->stc.vals[2]))[y];
  2330.       k = ((long *)(sd->stc.vals[3]))[k];
  2331.    }                                                       /* direct */
  2332. /*
  2333.  * compute the long-representation of gx_color_index
  2334.  */
  2335.    switch(mode) {
  2336.    case 0:
  2337.       rv = (((gx_color_index) m)<<22)|
  2338.            (((gx_color_index) y)<<12)|
  2339.            (((gx_color_index) k)<< 2)|mode;
  2340.       break;
  2341.    case 1:
  2342.       rv = (((gx_color_index) c)<<22)|
  2343.            (((gx_color_index) y)<<12)|
  2344.            (((gx_color_index) k)<< 2)|mode;
  2345.       break;
  2346.    case 2:
  2347.       rv = (((gx_color_index) c)<<22)|
  2348.            (((gx_color_index) m)<<12)|
  2349.            (((gx_color_index) k)<< 2)|mode;
  2350.       break;
  2351.    default:
  2352.       rv = (((gx_color_index) k)<< 2)|mode;
  2353.       break;
  2354.    }
  2355.  
  2356. /*
  2357.  * We may need some swapping
  2358.  */
  2359. #if !arch_is_big_endian
  2360.    {
  2361.       union { stc_pixel cv; byte bv[4]; } ui,uo;
  2362.       ui.cv = rv;
  2363.       uo.bv[0] = ui.bv[3];
  2364.       uo.bv[1] = ui.bv[2];
  2365.       uo.bv[2] = ui.bv[1];
  2366.       uo.bv[3] = ui.bv[0];
  2367.       rv       = uo.cv;
  2368.    }
  2369. #endif
  2370.    return rv;
  2371. }
  2372.  
  2373. private int 
  2374. stc_map_color_cmyk10(gx_device *pdev, gx_color_index color,
  2375.                      gx_color_value prgb[3])
  2376. {
  2377.  
  2378.    stcolor_device *sd = (stcolor_device *) pdev;
  2379.    gx_color_value c,m,y;
  2380.  
  2381. /*
  2382.  * We may need some swapping
  2383.  */
  2384. #if !arch_is_big_endian
  2385.    union { stc_pixel cv; byte bv[4]; } ui,uo;
  2386.    ui.cv = color;
  2387.    uo.bv[0] = ui.bv[3];
  2388.    uo.bv[1] = ui.bv[2];
  2389.    uo.bv[2] = ui.bv[1];
  2390.    uo.bv[3] = ui.bv[0];
  2391.    color    = uo.cv;
  2392. #endif
  2393.  
  2394.    c    =   stc_expand(sd,3,(color>>2)&0x3ff);
  2395.  
  2396.    switch(color & 3) {
  2397.      case 0:
  2398.         m = stc_expand(sd,1,(color>>22) & 0x3ff);
  2399.         y = stc_expand(sd,2,(color>>12) & 0x3ff);
  2400.         break;
  2401.      case 1:
  2402.         m = c;
  2403.         c = stc_expand(sd,0,(color>>22) & 0x3ff);
  2404.         y = stc_expand(sd,2,(color>>12) & 0x3ff);
  2405.         break;
  2406.      case 2:
  2407.         y = c;
  2408.         c = stc_expand(sd,0,(color>>22) & 0x3ff);
  2409.         m = stc_expand(sd,1,(color>>12) & 0x3ff);
  2410.         break;
  2411.      default:
  2412.         m = c;
  2413.         y = c;
  2414.         break;
  2415.    }
  2416.  
  2417.    prgb[0] = gx_max_color_value - c;
  2418.    prgb[1] = gx_max_color_value - m;
  2419.    prgb[2] = gx_max_color_value - y;
  2420.  
  2421.    return 0;
  2422. }
  2423.  
  2424. /***
  2425.  *** Macros for parameter-handling
  2426.  ***/
  2427.  
  2428. #define set_param_array(A, D, S)\
  2429.     {A.data = D; A.size = S; A.persistent = false;}
  2430.  
  2431. #define stc_write_null(N)                        \
  2432.     set_param_array(pfa,defext,countof(defext))  \
  2433.     code = param_write_null(plist,N);            \
  2434.     if (code < 0) return code;
  2435.  
  2436. #define stc_write_xarray(I,Coding,Transfer)                  \
  2437.     if(sd->stc.sizc[I] > 0) {                                \
  2438.        set_param_array(pfa, sd->stc.extc[I],sd->stc.sizc[I]) \
  2439.        code = param_write_float_array(plist,Coding,&pfa);    \
  2440.     } else {                                                 \
  2441.        code = param_write_null(plist,Coding);                \
  2442.     }                                                        \
  2443.     if ( code < 0 ) return code;                             \
  2444.                                                              \
  2445.     if(sd->stc.sizv[I] > 0)                                  \
  2446.        set_param_array(pfa, sd->stc.extv[I],sd->stc.sizv[I]) \
  2447.     else                                                     \
  2448.        set_param_array(pfa,defext,countof(defext))           \
  2449.     code = param_write_float_array(plist,Transfer,&pfa);     \
  2450.     if ( code < 0 ) return code;
  2451.  
  2452. #define stc_read_null(N)                                   \
  2453.     code = param_read_null(plist,N);                       \
  2454.     if(code == gs_error_typecheck)                         \
  2455.        code = param_read_float_array(plist,N,&pfa);        \
  2456.     if(code < 0) param_signal_error(plist,N,code);         \
  2457.     error = error > code ? code : error;
  2458.  
  2459. #define stc_read_xarray(I,Coding,Transfer)                 \
  2460.     code = param_read_float_array(plist,Coding,&pfa);      \
  2461.     if((error == 0) && (code == 0)) {                      \
  2462.        if(pfa.size > 1) {                                  \
  2463.           sd->stc.extc[I] = (float *) pfa.data;            \
  2464.           sd->stc.sizc[I] = pfa.size;                      \
  2465.        } else {                                            \
  2466.           code = gs_error_rangecheck;                      \
  2467.        }                                                   \
  2468.     } else if(code < 0) {                                  \
  2469.        code = param_read_null(plist,Coding);               \
  2470.        if(code == 0) {                                     \
  2471.           sd->stc.extc[I] = NULL;                          \
  2472.           sd->stc.sizc[I] = 0;                             \
  2473.        }                                                   \
  2474.     }                                                      \
  2475.     if(code < 0) param_signal_error(plist,Coding,code);    \
  2476.     error = error > code ? code : error;                   \
  2477.     code = param_read_float_array(plist,Transfer,&pfa);    \
  2478.     if((error == 0) && (code == 0)) {                      \
  2479.        sd->stc.extv[I] = (float *) pfa.data;               \
  2480.        sd->stc.sizv[I] = pfa.size;                         \
  2481.     } else if(code < 0) {                                  \
  2482.        code = param_read_null(plist,Transfer);             \
  2483.        if(code == 0) {                                     \
  2484.           sd->stc.extv[I] = defext;                        \
  2485.           sd->stc.sizv[I] = countof(defext);               \
  2486.        }                                                   \
  2487.     }                                                      \
  2488.     if(code < 0) param_signal_error(plist,Transfer,code);  \
  2489.     error = error > code ? code : error;
  2490.  
  2491. /***
  2492.  *** Get parameters == Make them accessable via PostScript
  2493.  ***/
  2494.  
  2495. private int 
  2496. stc_get_params(gx_device *pdev, gs_param_list *plist)
  2497. {
  2498.    int code,nc;
  2499.    gs_param_string      ps;
  2500.    gs_param_float_array pfa;
  2501.    bool btmp;
  2502.    stcolor_device *sd = (stcolor_device *) pdev;
  2503.  
  2504.    code = gdev_prn_get_params(pdev, plist);
  2505.    if ( code < 0 ) return code;
  2506.  
  2507. /*
  2508.  * Export some readonly-Parameters, used by stcinfo.ps
  2509.  */
  2510.    param_string_from_string(ps,"1.91");
  2511.    code = param_write_string(plist,"Version",&ps);
  2512.    if ( code < 0 ) return code;
  2513.  
  2514.    code = param_write_int(plist,"BitsPerComponent",&sd->stc.bits);
  2515.    if ( code < 0 ) return code;
  2516.  
  2517.    if(sd->stc.algorithms.size > 0) {
  2518.      code = param_write_string_array(plist,"Algorithms",&sd->stc.algorithms);
  2519.    } else {
  2520.      code = param_write_null(plist,"Algorithms");
  2521.    }
  2522.    if ( code < 0 ) return code;
  2523.  
  2524. /*
  2525.  * Export OutputCode
  2526.  */
  2527.    switch(sd->stc.flags & STCCOMP) {
  2528.    case STCPLAIN: param_string_from_string(ps,"plain");     break;
  2529.    case STCDELTA: param_string_from_string(ps,"deltarow");  break;
  2530.    default:       param_string_from_string(ps,"runlength"); break;
  2531.    }
  2532.    code = param_write_string(plist,"OutputCode",&ps);
  2533.    if ( code < 0 ) return code;
  2534. /*
  2535.  * Export Model
  2536.  */
  2537.    switch(sd->stc.flags & STCMODEL) {
  2538.    case STCST800: param_string_from_string(ps,"st800");   break;
  2539.    case STCSTCII: param_string_from_string(ps,"stcii");   break;
  2540.    default:       param_string_from_string(ps,"stc");     break;
  2541.    }
  2542.    code = param_write_string(plist,"Model",&ps);
  2543.    if ( code < 0 ) return code;
  2544.  
  2545. /*
  2546.  * Export the booleans
  2547.  */
  2548. #define stc_write_flag(Mask,Name)                \
  2549.    btmp = sd->stc.flags & (Mask) ? true : false; \
  2550.    code = param_write_bool(plist,Name,&btmp);    \
  2551.    if ( code < 0 ) return code;
  2552.  
  2553.    stc_write_flag(STCUNIDIR,"Unidirectional")
  2554.    stc_write_flag(STCUWEAVE,"Microweave")
  2555.    btmp = sd->stc.flags & (STCUNIDIR|STCUWEAVE) ? false : true;
  2556.    code = param_write_bool(plist,"Softweave",&btmp);
  2557.    if ( code < 0 ) return code;
  2558.    stc_write_flag(STCNWEAVE,"noWeave")
  2559.    stc_write_flag(STCDFLAG0, "Flag0")
  2560.    stc_write_flag(STCDFLAG1, "Flag1")
  2561.    stc_write_flag(STCDFLAG2, "Flag2")
  2562.    stc_write_flag(STCDFLAG3, "Flag3")
  2563.    stc_write_flag(STCDFLAG4, "Flag4")
  2564.  
  2565. #undef stc_write_flag
  2566.  
  2567. #  define stc_write_int(Mask,Name,Val)         \
  2568.       code = param_write_int(plist,Name,&Val); \
  2569.       if ( code < 0 ) return code
  2570.  
  2571.    stc_write_int(STCBAND,  "escp_Band",  sd->stc.escp_m);
  2572.    stc_write_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
  2573.    stc_write_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
  2574.    stc_write_int(STCTOP,   "escp_Top",   sd->stc.escp_top);
  2575.    stc_write_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
  2576.  
  2577. #  undef stc_write_int
  2578.  
  2579.    code = param_write_string(plist,"escp_Init",&sd->stc.escp_init);
  2580.    code = param_write_string(plist,"escp_Release",&sd->stc.escp_release);
  2581.  
  2582.    if(sd->stc.dither != NULL) {
  2583.       param_string_from_string(ps,sd->stc.dither->name);
  2584.       code = param_write_string(plist,"Dithering",&ps);
  2585.    } else {
  2586.       code = param_write_null(plist,"Dithering");
  2587.    }
  2588.    if ( code < 0 ) return code;
  2589.  
  2590.    nc = sd->color_info.num_components;
  2591.  
  2592.    if(sd->stc.am != NULL) {
  2593.       if(     nc == 1) set_param_array(pfa, sd->stc.am, 3)
  2594.       else if(nc == 3) set_param_array(pfa, sd->stc.am, 9)
  2595.       else             set_param_array(pfa, sd->stc.am,16)
  2596.       code = param_write_float_array(plist,"ColorAdjustMatrix",&pfa);
  2597.    } else {
  2598.       code = param_write_null(plist,"ColorAdjustMatrix");
  2599.    }
  2600.    if ( code < 0 ) return code;
  2601.  
  2602.    if(nc == 1) {        /* DeviceGray */
  2603.  
  2604.       stc_write_xarray(0,"Kcoding","Ktransfer");
  2605.  
  2606.       stc_write_null("Rcoding"); stc_write_null("Rtransfer");
  2607.       stc_write_null("Gcoding"); stc_write_null("Gtransfer");
  2608.       stc_write_null("Bcoding"); stc_write_null("Btransfer");
  2609.  
  2610.       stc_write_null("Ccoding"); stc_write_null("Ctransfer");
  2611.       stc_write_null("Mcoding"); stc_write_null("Mtransfer");
  2612.       stc_write_null("Ycoding"); stc_write_null("Ytransfer");
  2613.  
  2614.    } else if(nc == 3) { /* DeviceRGB */
  2615.  
  2616.       stc_write_xarray(0,"Rcoding","Rtransfer");
  2617.       stc_write_xarray(1,"Gcoding","Gtransfer");
  2618.       stc_write_xarray(2,"Bcoding","Btransfer");
  2619.  
  2620.       stc_write_null("Ccoding"); stc_write_null("Ctransfer");
  2621.       stc_write_null("Mcoding"); stc_write_null("Mtransfer");
  2622.       stc_write_null("Ycoding"); stc_write_null("Ytransfer");
  2623.       stc_write_null("Kcoding"); stc_write_null("Ktransfer");
  2624.  
  2625.    } else {             /* DeviceCMYK */
  2626.  
  2627.       stc_write_xarray(0,"Ccoding","Ctransfer");
  2628.       stc_write_xarray(1,"Mcoding","Mtransfer");
  2629.       stc_write_xarray(2,"Ycoding","Ytransfer");
  2630.       stc_write_xarray(3,"Kcoding","Ktransfer");
  2631.  
  2632.       stc_write_null("Rcoding"); stc_write_null("Rtransfer");
  2633.       stc_write_null("Gcoding"); stc_write_null("Gtransfer");
  2634.       stc_write_null("Bcoding"); stc_write_null("Btransfer");
  2635.  
  2636.    }
  2637.    return code;
  2638. }
  2639.  
  2640. /***
  2641.  *** put parameters == Store them in the device-structure
  2642.  ***/
  2643.  
  2644. private int 
  2645. stc_put_params(gx_device *pdev, gs_param_list *plist)
  2646. {
  2647.    int code,error,i,l;
  2648.    bool b1,b2,b3;
  2649.    float fv,*fp;
  2650.    gs_param_string      ps;
  2651.    gs_param_string_array psa;
  2652.    gs_param_float_array pfa;
  2653.    stcolor_device *sd = (stcolor_device *) pdev;
  2654.    gx_device_color_info oldcolor;
  2655.    stc_t                oldstc;
  2656.  
  2657. /*
  2658.  * save old Values
  2659.  */
  2660.    memcpy(&oldcolor,&sd->color_info,sizeof(oldcolor));
  2661.    memcpy(&oldstc  ,&sd->stc       ,sizeof(oldstc  ));
  2662.  
  2663. /*
  2664.  * Arrrgh:
  2665.  * With Version 3.4x and above my simple minded read-only Parameters
  2666.  * do not work any more. So read them here for heavens sake.
  2667.  */
  2668.    code = param_read_string(plist,"Version",&ps);
  2669.    code = param_read_int(plist,"BitsPerComponent",&i);
  2670.    code = param_read_string_array(plist,"Algorithms",&psa);
  2671.  
  2672. /*
  2673.  * Fetch Major-Parameters (Model, Dithering, BitsPerPixel/BitsPerComponent)
  2674.  */
  2675.    error = 0;
  2676.  
  2677.    code  = param_read_string(plist,"Model",&ps);
  2678.    if(code == 0) {   /* Analyze the Model-String */
  2679. /*
  2680.  * Arrgh: I should have known, that internal strings are not zero-terminated.
  2681.  */
  2682.       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
  2683. #     define stc_putcmp(Name) \
  2684.         ((strlen(Name) != l) || (0 != strncmp(Name, (const char *)ps.data,l)))
  2685.  
  2686.       sd->stc.flags &= ~STCMODEL;
  2687.       if(     !stc_putcmp("st800"))  sd->stc.flags |= STCST800;
  2688.       else if(!stc_putcmp("stcii"))  sd->stc.flags |= STCSTCII;
  2689.  
  2690.    }                 /* Analyze the Model-String */
  2691.    if(code < 0) param_signal_error(plist,"Model",code);
  2692.    error = error > code ? code : error;
  2693.  
  2694. /* If we're running for st800, #components must be 1 */
  2695.    if(((sd->stc.flags & STCMODEL) == STCST800) &&
  2696.       (( sd->color_info.num_components > 1) ||
  2697.        ( sd->stc.dither                == NULL) ||
  2698.        ((sd->stc.dither->flags & 7)    > 1))) {
  2699.         sd->color_info.num_components  = 1;
  2700.         sd->stc.dither = NULL;
  2701.     }
  2702.  
  2703. /* Weaving isn't a feature for the st800 */
  2704.    if((sd->stc.flags & STCMODEL) == STCST800) {
  2705.       sd->stc.flags &= ~STCUWEAVE;
  2706.       sd->stc.flags |=  STCNWEAVE;
  2707.    } else if((sd->stc.flags & STCMODEL) == STCSTCII) { /* no SoftWeave */
  2708.       sd->stc.flags |=  STCNWEAVE;
  2709.    }
  2710.  
  2711.    code  = param_read_string(plist,"Dithering",&ps);
  2712.    if(code == 0) {                     /* lookup new value new value */
  2713.  
  2714.       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
  2715.  
  2716.       for(i = 0; stc_dither[i].name != NULL; ++i)
  2717.          if(!stc_putcmp(stc_dither[i].name)) break;
  2718.  
  2719.    } else if(sd->stc.dither != NULL) {  /* compute index of given value */
  2720.  
  2721.       i = sd->stc.dither - stc_dither;
  2722.  
  2723.    } else {                            /* find matching value */
  2724.  
  2725.       for(i = 0; stc_dither[i].name != NULL; ++i)
  2726.          if((stc_dither[i].flags & 7) == sd->color_info.num_components) break;
  2727.  
  2728.    }                                   /* we've got an index */
  2729.  
  2730.    if(stc_dither[i].name != NULL) { /* establish data */
  2731.  
  2732. /*
  2733.  * Establish new dithering algorithm & color-model
  2734.  */
  2735.       sd->stc.dither                = stc_dither+i;
  2736.       sd->color_info.num_components = sd->stc.dither->flags & 7;
  2737.   STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
  2738. # undef stc_sizeofitem
  2739.       if(((sd->stc.flags & STCMODEL)    == STCST800) &&
  2740.          ( sd->color_info.num_components > 1       ))
  2741.          code = gs_error_rangecheck;
  2742.  
  2743. /*
  2744.  * reset Parameters related to the color-model, if it changed
  2745.  */
  2746.  
  2747.       if(sd->color_info.num_components != oldcolor.num_components) {
  2748.  
  2749.          for(i = 0; i < sd->color_info.num_components; ++i) {
  2750.             sd->stc.extv[i]   = (float *) defext;
  2751.             sd->stc.sizv[i]   = countof(defext);
  2752.  
  2753.             sd->stc.extc[i] = NULL;
  2754.             sd->stc.sizc[i] = 0;
  2755.  
  2756.          }
  2757.  
  2758.          sd->stc.am = NULL;
  2759.  
  2760.       } else { /* guarantee, that extvals is present */
  2761.  
  2762.          for(i = 0; i < sd->color_info.num_components; ++i) {
  2763.             if(sd->stc.sizv[i] < 2) {
  2764.                sd->stc.extv[i]   = (float *) defext;
  2765.                sd->stc.sizv[i]   = countof(defext);
  2766.             }
  2767.          }
  2768.       }
  2769.  
  2770.       for(i = sd->color_info.num_components; i < 4; ++ i) { /* clear unused */
  2771.          sd->stc.extv[i]   = NULL;
  2772.          sd->stc.sizv[i]   = 0;
  2773.          sd->stc.vals[i]   = NULL;
  2774.  
  2775.          sd->stc.extc[i] = NULL;
  2776.          sd->stc.sizc[i] = 0;
  2777.          sd->stc.code[i] = NULL;
  2778.  
  2779.       }                                                     /* clear unused */
  2780.  
  2781. /*
  2782.  * Guess default depth from range of values
  2783.  */
  2784.       if((sd->stc.dither != oldstc.dither)||(oldstc.vals[0] == NULL)) {
  2785.  
  2786.          if((sd->stc.dither->flags & STC_CMYK10) != 0) {
  2787.  
  2788.             sd->stc.flags       |= STCCMYK10;
  2789.             sd->stc.bits         = 10;
  2790.             sd->color_info.depth = 32;
  2791.  
  2792.          } else {
  2793.  
  2794.             sd->stc.flags       &= ~STCCMYK10;
  2795.  
  2796.             if((sd->stc.dither->flags & STC_FLOAT) != STC_FLOAT) {
  2797.                fv = 2.0;
  2798.                for(i = 1;(i  < gx_color_value_bits) &&
  2799.                   (fv <= (sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]));
  2800.                  ++i) fv *= 2.0;
  2801.  
  2802.             } else {
  2803.                i = 8; /* arbitrary */
  2804.             }
  2805.  
  2806.             if((i*sd->color_info.num_components) > (sizeof(stc_pixel)*8)) {
  2807.  
  2808.                sd->stc.bits         = (sizeof(stc_pixel)*8) /
  2809.                                        sd->color_info.num_components;
  2810.                sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
  2811.  
  2812.             } else {
  2813.  
  2814.                sd->stc.bits         = i;
  2815.                sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
  2816.  
  2817.             }
  2818.          }
  2819.       }
  2820.  
  2821.    } else {
  2822.  
  2823.       code = gs_error_rangecheck;
  2824.  
  2825.    }               /* verify new value */
  2826.    if(code < 0) param_signal_error(plist,"Dithering",code);
  2827.    error = error > code ? code : error;
  2828.  
  2829. /*
  2830.  * now fetch the desired depth, if the algorithm allows it
  2831.  */
  2832. /*
  2833.  * Arrrgh: We get code == 0, even if nobody sets BitsPerPixel.
  2834.  *         The value is the old one, but this may cause trouble
  2835.  *         with CMYK10.
  2836.  */
  2837.    code = param_read_int(plist, "BitsPerPixel", &i);
  2838.    if((error == 0) && (code == 0) &&
  2839.       (((sd->stc.flags & STCCMYK10) == 0) || (i != sd->color_info.depth))) {
  2840.  
  2841.       if((1 > i) || (i > (sizeof(stc_pixel)*8)))
  2842.          code = gs_error_rangecheck;
  2843.       else
  2844.          sd->color_info.depth = i;
  2845.  
  2846.       sd->stc.bits = i / sd->color_info.num_components;
  2847.  
  2848.       if(1 > sd->stc.bits) code = gs_error_rangecheck;
  2849.  
  2850.       if((sd->stc.dither->flags & STC_DIRECT) &&
  2851.          (sd->stc.dither->flags & STC_CMYK10))
  2852.          code           = gs_error_rangecheck;
  2853.       else
  2854.          sd->stc.flags &= ~STCCMYK10;
  2855.  
  2856.    }
  2857.    if(code < 0) param_signal_error(plist,"BitsPerPixel",code);
  2858.    error = error > code ? code : error;
  2859.  
  2860. /*
  2861.  * Fetch OutputCode
  2862.  */
  2863.    code  = param_read_string(plist,"OutputCode",&ps);
  2864.    if(code == 0) {   /* Analyze the OutputCode-String */
  2865.  
  2866.       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
  2867.  
  2868.       sd->stc.flags &= ~STCCOMP;
  2869.       if(!stc_putcmp("plain"))         sd->stc.flags |= STCPLAIN;
  2870.       else if(!stc_putcmp("deltarow")) sd->stc.flags |= STCDELTA;
  2871.  
  2872.    }                 /* Analyze the OutputCode-String */
  2873.    if((sd->stc.flags & STCCOMP) == STCDELTA) {
  2874.       sd->stc.flags |=  STCUWEAVE;
  2875.       sd->stc.flags &= ~STCNWEAVE;
  2876.    }
  2877.    if(code < 0) param_signal_error(plist,"OutputCode",code);
  2878.    error = error > code ? code : error;
  2879.  
  2880. /*
  2881.  * fetch the weave-mode (noWeave wins)
  2882.  */
  2883.    b1 = sd->stc.flags & STCUWEAVE ? true : false;
  2884.    b2 = sd->stc.flags & STCNWEAVE ? true : false;
  2885.    b3 = sd->stc.flags & (STCUWEAVE|STCNWEAVE) ? false : true;
  2886.  
  2887.    code = param_read_bool(plist,"Microweave",&b1);
  2888.    if(code < 0) {
  2889.       param_signal_error(plist,"Microweave",code);
  2890.    } else if(code == 0) {
  2891.       if(b1) { b2 = false; b3 = false; }
  2892.    }
  2893.    error = error > code ? code : error;
  2894.  
  2895.    code = param_read_bool(plist,"noWeave",&b2);
  2896.    if(code < 0) {
  2897.       param_signal_error(plist,"noWeave",code);
  2898.    } else if (code == 0) {
  2899.       if(b2) { b1 = false; b3 = false; }
  2900.    }
  2901.    error = error > code ? code : error;
  2902.  
  2903.    code = param_read_bool(plist,"Softweave",&b3);
  2904.    if(code < 0) {
  2905.       param_signal_error(plist,"Softweave",code);
  2906.    } else if (code == 0) {
  2907.       if(b3) { b1 = false; b2 = false; }
  2908.    }
  2909.    error = error > code ? code : error;
  2910.  
  2911.    if(b1) sd->stc.flags |=  STCUWEAVE;
  2912.    else   sd->stc.flags &= ~STCUWEAVE;
  2913.  
  2914.    if(b2) sd->stc.flags |=  STCNWEAVE;
  2915.    else   sd->stc.flags &= ~STCNWEAVE;
  2916.  
  2917. /*
  2918.  * Check the simple Flags
  2919.  */
  2920. #  define stc_read_flag(Mask,Name)                \
  2921.       code = param_read_bool(plist,Name,&b1);     \
  2922.       if(code < 0) {                              \
  2923.          param_signal_error(plist,Name,code);     \
  2924.       } else if(code == 0) {                      \
  2925.          if(b1 == true) sd->stc.flags |=  Mask;   \
  2926.          else           sd->stc.flags &= ~(Mask); \
  2927.       }                                           \
  2928.       error = error > code ? code : error;
  2929.  
  2930.    stc_read_flag(STCUNIDIR,"Unidirectional")
  2931.    stc_read_flag(STCDFLAG0, "Flag0")
  2932.    stc_read_flag(STCDFLAG1, "Flag1")
  2933.    stc_read_flag(STCDFLAG2, "Flag2")
  2934.    stc_read_flag(STCDFLAG3, "Flag3")
  2935.    stc_read_flag(STCDFLAG4, "Flag4")
  2936.  
  2937. /*
  2938.  * Now deal with the escp-Stuff
  2939.  */
  2940. #  define stc_read_int(Mask,Name,Val)             \
  2941.       code = param_read_int(plist,Name,&Val);     \
  2942.       if(code < 0)                                \
  2943.          param_signal_error(plist,Name,code);     \
  2944.       else if(code == 0)                          \
  2945.          sd->stc.flags |= Mask;                   \
  2946.       error = error > code ? code : error
  2947.  
  2948.    stc_read_int(STCBAND,  "escp_Band",  sd->stc.escp_m);
  2949.    stc_read_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
  2950.    stc_read_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
  2951.    stc_read_int(STCTOP,   "escp_Top",   sd->stc.escp_top);
  2952.    stc_read_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
  2953.  
  2954. #  undef stc_read_int
  2955.  
  2956.    code = param_read_string(plist,"escp_Init",&sd->stc.escp_init);
  2957.    if(code == 0) sd->stc.flags |= STCINIT;
  2958.    error = error > code ? code : error;
  2959.  
  2960.    code = param_read_string(plist,"escp_Release",&sd->stc.escp_release);
  2961.    if(code == 0) sd->stc.flags |= STCRELEASE;
  2962.    error = error > code ? code : error;
  2963.  
  2964. /*
  2965.  * ColorAdjustMatrix must match the required size,
  2966.  * setting it explicitly to null, erases old matrix
  2967.  */
  2968.    code = param_read_float_array(plist,"ColorAdjustMatrix",&pfa);
  2969.    if((error == 0) && (code == 0)) {
  2970.       if(((sd->color_info.num_components == 1) && (pfa.size ==  3)) ||
  2971.          ((sd->color_info.num_components == 3) && (pfa.size ==  9)) ||
  2972.          ((sd->color_info.num_components == 4) && (pfa.size == 16)))
  2973.          sd->stc.am = (float *) pfa.data;
  2974.       else
  2975.          code =  gs_error_rangecheck;
  2976.    } else if(code < 0) {
  2977.       code = param_read_null(plist,"ColorAdjustMatrix");
  2978.       if(code == 0) sd->stc.am = NULL;
  2979.    }
  2980.    if(code < 0) param_signal_error(plist,"ColorAdjustMatrix",code);
  2981.    error = error > code ? code : error;
  2982.  
  2983. /*
  2984.  * Read the external array-Parameters
  2985.  */
  2986.    if(sd->color_info.num_components == 1) {        /* DeviceGray */
  2987.  
  2988.       stc_read_xarray(0,"Kcoding","Ktransfer");
  2989.  
  2990.       stc_read_null("Rcoding"); stc_read_null("Rtransfer");
  2991.       stc_read_null("Gcoding"); stc_read_null("Gtransfer");
  2992.       stc_read_null("Bcoding"); stc_read_null("Btransfer");
  2993.  
  2994.       stc_read_null("Ccoding"); stc_read_null("Ctransfer");
  2995.       stc_read_null("Mcoding"); stc_read_null("Mtransfer");
  2996.       stc_read_null("Ycoding"); stc_read_null("Ytransfer");
  2997.  
  2998.    } else if(sd->color_info.num_components == 3) { /* DeviceRGB */
  2999.  
  3000.       stc_read_xarray(0,"Rcoding","Rtransfer");
  3001.       stc_read_xarray(1,"Gcoding","Gtransfer");
  3002.       stc_read_xarray(2,"Bcoding","Btransfer");
  3003.  
  3004.       stc_read_null("Ccoding"); stc_read_null("Ctransfer");
  3005.       stc_read_null("Mcoding"); stc_read_null("Mtransfer");
  3006.       stc_read_null("Ycoding"); stc_read_null("Ytransfer");
  3007.       stc_read_null("Kcoding"); stc_read_null("Ktransfer");
  3008.  
  3009.    } else {                                        /* DeviceCMYK */
  3010.  
  3011.       stc_read_xarray(0,"Ccoding","Ctransfer");
  3012.       stc_read_xarray(1,"Mcoding","Mtransfer");
  3013.       stc_read_xarray(2,"Ycoding","Ytransfer");
  3014.       stc_read_xarray(3,"Kcoding","Ktransfer");
  3015.  
  3016.       stc_read_null("Rcoding"); stc_read_null("Rtransfer");
  3017.       stc_read_null("Gcoding"); stc_read_null("Gtransfer");
  3018.       stc_read_null("Bcoding"); stc_read_null("Btransfer");
  3019.  
  3020.    }
  3021. /*
  3022.  * Update remaining color_info values
  3023.  */
  3024.    if(error == 0) {
  3025.  
  3026. /*    compute #values from the component-bits */
  3027.       sd->color_info.max_gray  = sd->stc.bits < gx_color_value_bits ?
  3028.                             (1<<sd->stc.bits)-1 : gx_max_color_value;
  3029.  
  3030. /*    An integer-algorithm might reduce the number of values */
  3031.       if(((sd->stc.dither->flags & STC_TYPE) != STC_FLOAT) &&
  3032.          ((sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]) <
  3033.            sd->color_info.max_gray))
  3034.          sd->color_info.max_gray =
  3035.                 sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]+0.5;
  3036.  
  3037.       sd->color_info.max_color = sd->color_info.num_components < 3 ? 0 :
  3038.                                  sd->color_info.max_gray;
  3039.       sd->color_info.dither_grays =
  3040.           sd->color_info.max_gray < gx_max_color_value ?
  3041.           sd->color_info.max_gray+1  : gx_max_color_value;
  3042.       sd->color_info.dither_colors  = sd->color_info.num_components < 3 ? 0 :
  3043.           sd->color_info.dither_grays;
  3044.    }
  3045.  
  3046. /*
  3047.  * Call superclass-Update
  3048.  */
  3049.  
  3050.    code = gdev_prn_put_params(pdev, plist);
  3051.    error = error > code ? code : error;
  3052.  
  3053. /*
  3054.  * Arrrgh, writing BitsPerPixel is really *VERY* special:
  3055.  *    gdev_prn_put_params verifies, that the external value
  3056.  *    is written, if not, it raises a rangecheck-error.
  3057.  *    On the other hand ghostscript is quite unhappy with odd
  3058.  *    values, so we do the necessary rounding *AFTER* the
  3059.  *    "superclass-Update".
  3060.  */
  3061.  
  3062.    if(sd->color_info.depth ==  3) sd->color_info.depth = 4;
  3063.    else if(sd->color_info.depth > 4)
  3064.       sd->color_info.depth =  (sd->color_info.depth+7) & ~7;
  3065.  
  3066. /*
  3067.  * Allocate the storage for the arrays in memory
  3068.  */
  3069.    if(error == 0) { /* Allocate new external-arrays */
  3070.  
  3071.      for(i = 0; i < sd->color_info.num_components; ++i){ /* Active components */
  3072.         int j;
  3073.  
  3074.         if((sd->stc.extv[i] != oldstc.extv[i]) &&
  3075.            (sd->stc.extv[i] != defext        )) { /* Value-Arrays */
  3076.  
  3077.            for(j = 0; j < i; ++j)
  3078.               if((sd->stc.sizv[j] == sd->stc.sizv[i]) &&
  3079.                  (memcmp(sd->stc.extv[j],sd->stc.extv[i],
  3080.                          sd->stc.sizv[i]*sizeof(float)) == 0)) break;
  3081.  
  3082.            if(j < i) {
  3083.               sd->stc.extv[i] = sd->stc.extv[j];
  3084.            } else {
  3085.               fp = gs_malloc(sd->stc.sizv[i],sizeof(float),"stc_put_params");
  3086.               if(fp != NULL)
  3087.                  memcpy(fp,sd->stc.extv[i],sd->stc.sizv[i]*sizeof(float));
  3088.                else
  3089.                  code = gs_error_VMerror;
  3090.                sd->stc.extv[i] = fp;
  3091.            }
  3092.         }                                         /* Value-Arrays */
  3093.  
  3094.         if((sd->stc.sizc[i] > 1) &&
  3095.            (sd->stc.extc[i] != oldstc.extc[i])) { /* Code-Arrays */
  3096.  
  3097.            for(j = 0; j < i; ++j)
  3098.               if((sd->stc.sizc[j] == sd->stc.sizc[i]) &&
  3099.                  (memcmp(sd->stc.extc[j],sd->stc.extc[i],
  3100.                          sd->stc.sizc[i]*sizeof(float)) == 0)) break;
  3101.  
  3102.            if(j < i) {
  3103.               sd->stc.extc[i] = sd->stc.extc[j];
  3104.            } else {
  3105.               fp = gs_malloc(sd->stc.sizc[i],sizeof(float),"stc_put_params");
  3106.               if(fp != NULL)
  3107.                  memcpy(fp,sd->stc.extc[i],sd->stc.sizc[i]*sizeof(float));
  3108.                else
  3109.                  code = gs_error_VMerror;
  3110.                sd->stc.extc[i] = fp;
  3111.            }
  3112.         }                                         /* Code-Arrays */
  3113.  
  3114.      }                                                   /* Active components */
  3115.  
  3116.      if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
  3117.         if(     sd->color_info.num_components == 1) i =  3;
  3118.         else if(sd->color_info.num_components == 3) i =  9;
  3119.         else                                        i = 16;
  3120.         fp = gs_malloc(i,sizeof(float),"stc_put_params");
  3121.         if(fp != NULL) memcpy(fp,sd->stc.am,i*sizeof(float));
  3122.         else           code = gs_error_VMerror;
  3123.         sd->stc.am = fp;
  3124.      }
  3125.  
  3126.      if(sd->stc.escp_init.data != oldstc.escp_init.data) {
  3127.         byte *ip = NULL;
  3128.  
  3129.         if(sd->stc.escp_init.size > 0) {
  3130.            ip = gs_malloc(sd->stc.escp_init.size,1,"stcolor/init");
  3131.            if(ip == NULL) {
  3132.               code = gs_error_VMerror;
  3133.               sd->stc.escp_init.size = 0;
  3134.            } else {
  3135.               memcpy(ip,sd->stc.escp_init.data,sd->stc.escp_init.size);
  3136.            }
  3137.         }
  3138.         sd->stc.escp_init.data       = ip;
  3139.         sd->stc.escp_init.persistent = false;
  3140.      }
  3141.  
  3142.      if(sd->stc.escp_release.data != oldstc.escp_release.data) {
  3143.         byte *ip = NULL;
  3144.  
  3145.         if(sd->stc.escp_release.size > 0) {
  3146.            ip = gs_malloc(sd->stc.escp_release.size,1,"stcolor/release");
  3147.            if(ip == NULL) {
  3148.               code = gs_error_VMerror;
  3149.               sd->stc.escp_release.size = 0;
  3150.            } else {
  3151.               memcpy(ip,sd->stc.escp_release.data,sd->stc.escp_release.size);
  3152.            }
  3153.         }
  3154.         sd->stc.escp_release.data       = ip;
  3155.         sd->stc.escp_release.persistent = false;
  3156.      }
  3157.  
  3158.      if(code < 0) { /* free newly allocated arrays */
  3159.  
  3160.         if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
  3161.            if(     sd->color_info.num_components == 1) i =  3;
  3162.            else if(sd->color_info.num_components == 3) i =  9;
  3163.            else                                        i = 16;
  3164.            gs_free(sd->stc.am,i,sizeof(float),"stc_put_params");
  3165.         }
  3166.  
  3167.         if((sd->stc.escp_init.data != NULL) &&
  3168.            (sd->stc.escp_init.data != oldstc.escp_init.data))
  3169.            gs_free((byte *) sd->stc.escp_init.data,sd->stc.escp_init.size,1,
  3170.               "stcolor/init");
  3171.  
  3172.         if((sd->stc.escp_release.data != NULL) &&
  3173.            (sd->stc.escp_release.data != oldstc.escp_release.data))
  3174.            gs_free((byte *) sd->stc.escp_release.data,sd->stc.escp_release.
  3175.               size,1,"stcolor/release");
  3176.  
  3177.         for(i = 0; i < sd->color_info.num_components; ++i) { /* components */
  3178.            int j;
  3179.  
  3180.            if((sd->stc.extc[i] != NULL) &&
  3181.               (sd->stc.extc[i] != defext) &&
  3182.               (sd->stc.extc[i] != oldstc.extc[i])) {
  3183.  
  3184.               for(j = 0; j < i; ++j)
  3185.                  if(sd->stc.extc[i] == sd->stc.extc[j]) break;
  3186.  
  3187.               if(i == j) gs_free(sd->stc.extc[i],sd->stc.sizc[i],sizeof(float),
  3188.                             "stc_put_params");
  3189.            }
  3190.  
  3191.            if((sd->stc.extv[i] != NULL) &&
  3192.               (sd->stc.extv[i] != oldstc.extv[i]) &&
  3193.               (sd->stc.extv[i] != defext)) {
  3194.  
  3195.               for(j = 0; j < i; ++j)
  3196.                  if(sd->stc.extv[i] == sd->stc.extv[j]) break;
  3197.  
  3198.               if(i == j) gs_free(sd->stc.extv[i],sd->stc.sizv[i],sizeof(float),
  3199.                             "stc_put_params");
  3200.            }
  3201.         }                                                    /* components */
  3202.      }              /* free newly allocated arrays */
  3203.    }                /* Allocate new arrays */
  3204.    error = error > code ? code : error;
  3205.  
  3206. /*
  3207.  * finally decide upon restore or release of old, unused data
  3208.  */
  3209.    if(error != 0) { /* Undo changes */
  3210.  
  3211.       memcpy(&sd->color_info,&oldcolor,sizeof(oldcolor));
  3212.       memcpy(&sd->stc       ,&oldstc  ,sizeof(oldstc  ));
  3213.    } else {        /* undo / release */
  3214.  
  3215.       if((oldstc.escp_init.data != NULL) &&
  3216.          (oldstc.escp_init.data != sd->stc.escp_init.data)) {
  3217.             gs_free((byte *)oldstc.escp_init.data,
  3218.                             oldstc.escp_init.size,1,"stcolor/init");
  3219.       }
  3220.  
  3221.       if((oldstc.escp_release.data != NULL) &&
  3222.          (oldstc.escp_release.data != sd->stc.escp_release.data)) {
  3223.             gs_free((byte *)oldstc.escp_release.data,
  3224.                             oldstc.escp_release.size,1,"stcolor/release");
  3225.       }
  3226.  
  3227.       if((oldstc.am != NULL) && (oldstc.am != sd->stc.am)) {
  3228.          if(     oldcolor.num_components == 1) i =  3;
  3229.          else if(oldcolor.num_components == 3) i =  9;
  3230.          else                                  i = 16;
  3231.          gs_free(oldstc.am,i,sizeof(float),"stc_put_params");
  3232.       }
  3233.  
  3234.       for(i = 0; i < 4; ++i) {
  3235.          int j;
  3236.  
  3237.          if((oldstc.extc[i] != NULL) &&
  3238.             (oldstc.extc[i] != sd->stc.extc[i]) &&
  3239.             (oldstc.dither  != NULL) &&
  3240.             (oldstc.extc[i] != defext)) {
  3241.  
  3242.             for(j = 0; j < i; ++j) if(oldstc.extc[i] == oldstc.extc[j]) break;
  3243.  
  3244.             if(i == j) gs_free(oldstc.extc[i],oldstc.sizc[i],sizeof(float),
  3245.                             "stc_put_params");
  3246.          }
  3247.  
  3248.          if((oldstc.extv[i] != NULL) &&
  3249.             (oldstc.extv[i] != sd->stc.extv[i]) &&
  3250.             (oldstc.extv[i] != defext)) {
  3251.  
  3252.             for(j = 0; j < i; ++j) if(oldstc.extv[i] == oldstc.extv[j]) break;
  3253.  
  3254.             if(i == j) gs_free(oldstc.extv[i],oldstc.sizv[i],sizeof(float),
  3255.                             "stc_put_params");
  3256.          }
  3257.       }
  3258.  
  3259. /*
  3260.  * Close the device if colormodel changed or recomputation
  3261.  * of internal arrays is required
  3262.  */
  3263.       if(sd->is_open) { /* we might need to close it */
  3264.          bool doclose = false;
  3265.          if((sd->color_info.num_components != oldcolor.num_components) ||
  3266.             (sd->color_info.depth          != oldcolor.depth         ) ||
  3267.             (sd->stc.bits                  != oldstc.bits            ) ||
  3268.             (sd->stc.dither                != oldstc.dither          ))
  3269.             doclose = true;
  3270.  
  3271.          for(i = 0; i < sd->color_info.num_components; ++i) {
  3272.             if(sd->stc.extv[i] != oldstc.extv[i]) doclose = true;
  3273.             if(sd->stc.extc[i] != oldstc.extc[i]) doclose = true;
  3274.          }
  3275.          if(doclose) {
  3276.             stc_freedata(&oldstc);
  3277.             for(i = 0; i < 4; ++i) {
  3278.                sd->stc.vals[i] = NULL;
  3279.                sd->stc.code[i] = NULL;
  3280.             }
  3281.  
  3282.             gs_closedevice(pdev);
  3283.          }
  3284.       }                 /* we might need to close it */
  3285.  
  3286.    }
  3287.  
  3288.    return error;
  3289. }
  3290. /*
  3291.  * 1Bit CMYK-Algorithm
  3292.  */
  3293.  
  3294. private int
  3295. stc_gscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
  3296. {
  3297.  
  3298.    byte *ip = in;
  3299.    int   error = 0;
  3300.  
  3301.  
  3302. /* ============================================================= */
  3303.    if(npixel > 0) {  /* npixel >  0 -> scanline-processing       */
  3304. /* ============================================================= */
  3305.  
  3306.       int p;
  3307.  
  3308. /*
  3309.  *    simply split the two pixels rsiding in a byte
  3310.  */
  3311.       for(p = npixel; p > 0; --p) { /* loop over pixels */
  3312.          byte tmp =*ip++;
  3313.  
  3314.          *out++ = (tmp>>4) & 15;
  3315.          if(--p <= 0) break;
  3316.  
  3317.          *out++ =  tmp     & 15;
  3318.  
  3319.       }                                   /* loop over pixels */
  3320.  
  3321. /* ============================================================= */
  3322.    } else {          /* npixel <= 0 -> initialisation            */
  3323. /* ============================================================= */
  3324.  
  3325. /*    we didn't check for the white-calls above, so this may cause errors */
  3326.       if(sdev->stc.dither->flags & STC_WHITE)              error = -1;
  3327.  
  3328. /*    if we're not setup for bytes, this is an error too */
  3329.       if((sdev->stc.dither->flags & STC_TYPE) != STC_BYTE) error = -2;
  3330.  
  3331. /*    This IS a direct-driver, so STC_DIRECT must be set! */
  3332.       if((sdev->stc.dither->flags & STC_DIRECT) == 0)      error = -3;
  3333.  
  3334. /*    and cmyk-mode is the only supported mode */
  3335.       if(sdev->color_info.num_components != 4)             error = -4;
  3336.  
  3337. /*    and we support only 4Bit-Depth here */
  3338.       if(sdev->color_info.depth != 4)                      error = -5;
  3339.  
  3340. /* ============================================================= */
  3341.    } /* scanline-processing or initialisation */
  3342. /* ============================================================= */
  3343.  
  3344.    return error;
  3345. }
  3346.  
  3347. /*
  3348.  * The following is an algorithm under test
  3349.  */
  3350. private int
  3351. stc_hscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
  3352. {
  3353.  
  3354. /* ============================================================= */
  3355.    if(npixel < 0) {  /* npixel <= 0 -> initialisation            */
  3356. /* ============================================================= */
  3357.  
  3358.       int i,i2do;
  3359.       long *lp = (long *) buf;
  3360.  
  3361. /* CMYK-only algorithm */
  3362.       if( sdev->color_info.num_components != 4)                      return -1;
  3363.  
  3364. /*
  3365.  * check wether stcdither & TYPE are correct
  3366.  */
  3367.       if(( sdev->stc.dither                    == NULL) ||
  3368.          ((sdev->stc.dither->flags & STC_TYPE) != STC_LONG))         return -2;
  3369.  
  3370. /*
  3371.  * check wether the buffer-size is sufficiently large
  3372.  */
  3373.       if(((sdev->stc.dither->flags/STC_SCAN) < 1) ||
  3374.          ( sdev->stc.dither->bufadd          <
  3375.           (1 + 2*sdev->color_info.num_components)))                  return -3;
  3376.  
  3377. /*
  3378.  * must have STC_CMYK10, STC_DIRECT, but not STC_WHITE
  3379.  */
  3380.       if((sdev->stc.dither->flags & STC_CMYK10) == 0)                return -4;
  3381.       if((sdev->stc.dither->flags & STC_DIRECT) == 0)                return -5;
  3382.       if((sdev->stc.dither->flags & STC_WHITE ) != 0)                return -6;
  3383.  
  3384. /*
  3385.  * Must have values between 0-1023.0
  3386.  */
  3387.       if((sdev->stc.dither->minmax[0] !=    0.0) ||
  3388.          (sdev->stc.dither->minmax[1] != 1023.0))                    return -7;
  3389. /*
  3390.  * initialize buffer
  3391.  */
  3392.  
  3393.      i2do            = 1 + 8 - 4 * npixel;
  3394.      lp[0] = 0;
  3395.  
  3396.       if(sdev->stc.flags & STCDFLAG0) {
  3397.         for(i = 1; i < i2do; ++i) lp[i] = 0;
  3398.       } else {
  3399.         for(i = 1; i < i2do; ++i)  lp[i] = (rand() % 381) - 190;
  3400.       }
  3401.  
  3402. /* ============================================================= */
  3403.    } else {  /* npixel > 0 && in != NULL  -> scanline-processing */
  3404. /* ============================================================= */
  3405.  
  3406.       long errc[4],*errv;
  3407.       int             step  = buf[0] ? -1 : 1;
  3408.       stc_pixel *ip    =  (stc_pixel *) in;
  3409.  
  3410.       buf[0] = ~ buf[0];
  3411.       errv   =  (long *) buf + 5;
  3412.  
  3413.       if(step < 0) {
  3414.         ip   += npixel-1;
  3415.         out  += npixel-1;
  3416.         errv += 4*(npixel-1);
  3417.       }
  3418.  
  3419.       errc[0] = 0; errc[1] = 0; errc[2] = 0; errc[3] = 0;
  3420.  
  3421.       while(npixel-- > 0) {
  3422.  
  3423.          register  stc_pixel ci,mode;
  3424.          register  long           k,v,n;
  3425.          register  int pixel; /* internal pixel-value */
  3426.  
  3427.          ci      = *ip; ip += step;
  3428.  
  3429.          mode    = ci & 3;
  3430.          k       = (ci>>2) & 0x3ff;
  3431.          pixel   = 0;
  3432.  
  3433.          v       = k+errv[3]+((7*errc[3])>>4);
  3434.  
  3435.          if(mode == 3) { /* only Black allowed to fire */
  3436.  
  3437.             if(v > 511) {
  3438.                v     -= 1023;
  3439.                pixel  = BLACK;
  3440.             }
  3441.             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3442.             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
  3443.             errc[3]            = v;
  3444.  
  3445.             errv[0] = errv[0] < -190 ? -190 : errv[0] < 190 ? errv[0] : 190;
  3446.             errv[1] = errv[1] < -190 ? -190 : errv[1] < 190 ? errv[1] : 190;
  3447.             errv[2] = errv[2] < -190 ? -190 : errv[2] < 190 ? errv[2] : 190;
  3448.  
  3449.             errc[0] = 0; errc[1] = 0; errc[2] = 0;
  3450.  
  3451.          } else if(v > 511) { /* black known to fire */
  3452.  
  3453.             v    -= 1023;
  3454.             pixel = BLACK;
  3455.  
  3456.             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3457.             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
  3458.             errc[3]            = v;
  3459.  
  3460.             n = (ci>>12) & 0x3ff;
  3461.  
  3462.             if(mode == 2) { v = k; }
  3463.             else          { v = n; n = (ci>>22) & 0x3ff; }
  3464.  
  3465.             v += errv[2]+((7*errc[2])>>4)-1023;
  3466.             if(v < -511) v = -511;
  3467.             errv[2-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3468.             errv[2]            = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
  3469.             errc[2]            = v;
  3470.  
  3471.             if(mode == 1) { v = k; }
  3472.             else          { v = n; n = (ci>>22) & 0x3ff; }
  3473.  
  3474.             v += errv[1]+((7*errc[1])>>4)-1023;
  3475.             if(v < -511) v = -511;
  3476.             errv[1-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3477.             errv[1]            = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
  3478.             errc[1]            = v;
  3479.  
  3480.             if(mode == 0) v = k;
  3481.             else          v = n;
  3482.  
  3483.             v += errv[0]+((7*errc[0])>>4)-1023;
  3484.             if(v < -511) v = -511;
  3485.             errv[0-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3486.             errv[0]            = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
  3487.             errc[0]            = v;
  3488.  
  3489.          } else { /* Black does not fire initially */
  3490.  
  3491.             long kv = v; /* Black computed after colors */
  3492.  
  3493.             n = (ci>>12) & 0x3ff;
  3494.  
  3495.             if(mode == 2) { v = k; }
  3496.             else          { v = n; n = (ci>>22) & 0x3ff; }
  3497.  
  3498.             v += errv[2]+((7*errc[2])>>4);
  3499.             if(v > 511) {
  3500.                pixel |= YELLOW;
  3501.                v     -= 1023;
  3502.             }
  3503.             errv[2-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3504.             errv[2]            = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
  3505.             errc[2]            = v;
  3506.  
  3507.             if(mode == 1) { v = k; }
  3508.             else          { v = n; n = (ci>>22) & 0x3ff; }
  3509.  
  3510.             v += errv[1]+((7*errc[1])>>4);
  3511.             if(v > 511) {
  3512.                pixel |= MAGENTA;
  3513.                v     -= 1023;
  3514.             }
  3515.             errv[1-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3516.             errv[1]            = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
  3517.             errc[1]            = v;
  3518.  
  3519.             if(mode == 0) v = k;
  3520.             else          v = n;
  3521.  
  3522.             v += errv[0]+((7*errc[0])>>4);
  3523.             if(v > 511) {
  3524.                pixel |= CYAN;
  3525.                v     -= 1023;
  3526.             }
  3527.             errv[0-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3528.             errv[0]            = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
  3529.             errc[0]            = v;
  3530.  
  3531.             v = kv;
  3532.             if(pixel == (CYAN|MAGENTA|YELLOW)) {
  3533.                pixel = BLACK;
  3534.                v     = v > 511 ? v-1023 : -511;
  3535.             }
  3536.             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3537.             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
  3538.             errc[3]            = v;
  3539.  
  3540.          }
  3541.  
  3542.          errv += step<<2;
  3543.          *out  = pixel; out += step;
  3544.  
  3545.       }                                         /* loop over pixels */
  3546.  
  3547. /* ============================================================= */
  3548.    } /* initialisation, white or scanline-processing             */
  3549. /* ============================================================= */
  3550.  
  3551.    return 0;
  3552. }
  3553.